提交 ec5f99f9 编写于 作者: R Rossen Stoyanchev

Add mutate() to RequestMappingInfo

Closes gh-26428
上级 03f1b650
/*
* Copyright 2002-2020 the original author or authors.
* Copyright 2002-2021 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
......@@ -89,29 +89,27 @@ public final class RequestMappingInfo implements RequestCondition<RequestMapping
private final int hashCode;
private final BuilderConfiguration options;
/**
* Full constructor with a mapping name.
* @deprecated as of 5.3.4 in favor using {@link RequestMappingInfo.Builder} via {@link #paths(String...)}.
*/
@Deprecated
public RequestMappingInfo(@Nullable String name, @Nullable PatternsRequestCondition patterns,
@Nullable RequestMethodsRequestCondition methods, @Nullable ParamsRequestCondition params,
@Nullable HeadersRequestCondition headers, @Nullable ConsumesRequestCondition consumes,
@Nullable ProducesRequestCondition produces, @Nullable RequestCondition<?> custom) {
this.name = (StringUtils.hasText(name) ? name : null);
this.patternsCondition = (patterns != null ? patterns : EMPTY_PATTERNS);
this.methodsCondition = (methods != null ? methods : EMPTY_REQUEST_METHODS);
this.paramsCondition = (params != null ? params : EMPTY_PARAMS);
this.headersCondition = (headers != null ? headers : EMPTY_HEADERS);
this.consumesCondition = (consumes != null ? consumes : EMPTY_CONSUMES);
this.producesCondition = (produces != null ? produces : EMPTY_PRODUCES);
this.customConditionHolder = (custom != null ? new RequestConditionHolder(custom) : EMPTY_CUSTOM);
this.hashCode = calculateHashCode(
this.patternsCondition, this.methodsCondition, this.paramsCondition, this.headersCondition,
this.consumesCondition, this.producesCondition, this.customConditionHolder);
this(name, patterns, methods, params, headers, consumes, produces, custom, new BuilderConfiguration());
}
/**
* Creates a new instance with the given request conditions.
* Create an instance with the given conditions.
* @deprecated as of 5.3.4 in favor using {@link RequestMappingInfo.Builder} via {@link #paths(String...)}.
*/
@Deprecated
public RequestMappingInfo(@Nullable PatternsRequestCondition patterns,
@Nullable RequestMethodsRequestCondition methods, @Nullable ParamsRequestCondition params,
@Nullable HeadersRequestCondition headers, @Nullable ConsumesRequestCondition consumes,
......@@ -122,12 +120,35 @@ public final class RequestMappingInfo implements RequestCondition<RequestMapping
/**
* Re-create a RequestMappingInfo with the given custom request condition.
* @deprecated since 5.3.4 in favor of using a {@link Builder} via {@link #mutate()}.
*/
@Deprecated
public RequestMappingInfo(RequestMappingInfo info, @Nullable RequestCondition<?> customRequestCondition) {
this(info.name, info.patternsCondition, info.methodsCondition, info.paramsCondition, info.headersCondition,
info.consumesCondition, info.producesCondition, customRequestCondition);
}
private RequestMappingInfo(@Nullable String name, @Nullable PatternsRequestCondition patterns,
@Nullable RequestMethodsRequestCondition methods, @Nullable ParamsRequestCondition params,
@Nullable HeadersRequestCondition headers, @Nullable ConsumesRequestCondition consumes,
@Nullable ProducesRequestCondition produces, @Nullable RequestCondition<?> custom,
BuilderConfiguration options) {
this.name = (StringUtils.hasText(name) ? name : null);
this.patternsCondition = (patterns != null ? patterns : EMPTY_PATTERNS);
this.methodsCondition = (methods != null ? methods : EMPTY_REQUEST_METHODS);
this.paramsCondition = (params != null ? params : EMPTY_PARAMS);
this.headersCondition = (headers != null ? headers : EMPTY_HEADERS);
this.consumesCondition = (consumes != null ? consumes : EMPTY_CONSUMES);
this.producesCondition = (produces != null ? produces : EMPTY_PRODUCES);
this.customConditionHolder = (custom != null ? new RequestConditionHolder(custom) : EMPTY_CUSTOM);
this.options = options;
this.hashCode = calculateHashCode(
this.patternsCondition, this.methodsCondition, this.paramsCondition, this.headersCondition,
this.consumesCondition, this.producesCondition, this.customConditionHolder);
}
/**
* Return the name for this mapping, or {@code null}.
......@@ -219,7 +240,7 @@ public final class RequestMappingInfo implements RequestCondition<RequestMapping
RequestConditionHolder custom = this.customConditionHolder.combine(other.customConditionHolder);
return new RequestMappingInfo(name, patterns,
methods, params, headers, consumes, produces, custom.getCondition());
methods, params, headers, consumes, produces, custom.getCondition(), this.options);
}
@Nullable
......@@ -275,7 +296,7 @@ public final class RequestMappingInfo implements RequestCondition<RequestMapping
return null;
}
return new RequestMappingInfo(this.name, patterns,
methods, params, headers, consumes, produces, custom.getCondition());
methods, params, headers, consumes, produces, custom.getCondition(), this.options);
}
/**
......@@ -381,6 +402,15 @@ public final class RequestMappingInfo implements RequestCondition<RequestMapping
}
/**
* Return a builder to create a new RequestMappingInfo by modifying this one.
* @return a builder to create a new, modified instance
* @since 5.3.4
*/
public Builder mutate() {
return new MutateBuilder(this);
}
/**
* Create a new {@code RequestMappingInfo.Builder} with the given paths.
* @param paths the paths to use
......@@ -546,7 +576,6 @@ public final class RequestMappingInfo implements RequestCondition<RequestMapping
@Override
public RequestMappingInfo build() {
PathPatternParser parser = (this.options.getPatternParser() != null ?
this.options.getPatternParser() : PathPatternParser.defaultInstance);
......@@ -564,10 +593,11 @@ public final class RequestMappingInfo implements RequestCondition<RequestMapping
null : new ConsumesRequestCondition(this.consumes, this.headers),
ObjectUtils.isEmpty(this.produces) && !this.hasAccept ?
null : new ProducesRequestCondition(this.produces, this.headers, contentTypeResolver),
this.customCondition);
this.customCondition,
this.options);
}
private static List<PathPattern> parse(String[] patterns, PathPatternParser parser) {
static List<PathPattern> parse(String[] patterns, PathPatternParser parser) {
if (isEmpty(patterns)) {
return Collections.emptyList();
}
......@@ -581,7 +611,7 @@ public final class RequestMappingInfo implements RequestCondition<RequestMapping
return result;
}
private static boolean isEmpty(String[] patterns) {
static boolean isEmpty(String[] patterns) {
if (!ObjectUtils.isEmpty(patterns)) {
for (String pattern : patterns) {
if (StringUtils.hasText(pattern)) {
......@@ -594,6 +624,113 @@ public final class RequestMappingInfo implements RequestCondition<RequestMapping
}
private static class MutateBuilder implements Builder {
@Nullable
private String name;
@Nullable
private PatternsRequestCondition patternsCondition;
private RequestMethodsRequestCondition methodsCondition;
private ParamsRequestCondition paramsCondition;
private HeadersRequestCondition headersCondition;
private ConsumesRequestCondition consumesCondition;
private ProducesRequestCondition producesCondition;
private RequestConditionHolder customConditionHolder;
private BuilderConfiguration options;
public MutateBuilder(RequestMappingInfo other) {
this.name = other.name;
this.patternsCondition = other.patternsCondition;
this.methodsCondition = other.methodsCondition;
this.paramsCondition = other.paramsCondition;
this.headersCondition = other.headersCondition;
this.consumesCondition = other.consumesCondition;
this.producesCondition = other.producesCondition;
this.customConditionHolder = other.customConditionHolder;
this.options = other.options;
}
@Override
public Builder paths(String... paths) {
PathPatternParser parser = (this.options.getPatternParser() != null ?
this.options.getPatternParser() : PathPatternParser.defaultInstance);
this.patternsCondition = (DefaultBuilder.isEmpty(paths) ?
null : new PatternsRequestCondition(DefaultBuilder.parse(paths, parser)));
return this;
}
@Override
public Builder methods(RequestMethod... methods) {
this.methodsCondition = (ObjectUtils.isEmpty(methods) ?
EMPTY_REQUEST_METHODS : new RequestMethodsRequestCondition(methods));
return this;
}
@Override
public Builder params(String... params) {
this.paramsCondition = (ObjectUtils.isEmpty(params) ?
EMPTY_PARAMS : new ParamsRequestCondition(params));
return this;
}
@Override
public Builder headers(String... headers) {
this.headersCondition = (ObjectUtils.isEmpty(headers) ?
EMPTY_HEADERS : new HeadersRequestCondition(headers));
return this;
}
@Override
public Builder consumes(String... consumes) {
this.consumesCondition = (ObjectUtils.isEmpty(consumes) ?
EMPTY_CONSUMES : new ConsumesRequestCondition(consumes));
return this;
}
@Override
public Builder produces(String... produces) {
this.producesCondition = (ObjectUtils.isEmpty(produces) ?
EMPTY_PRODUCES :
new ProducesRequestCondition(produces, null, this.options.getContentTypeResolver()));
return this;
}
@Override
public Builder mappingName(String name) {
this.name = name;
return this;
}
@Override
public Builder customCondition(RequestCondition<?> condition) {
this.customConditionHolder = new RequestConditionHolder(condition);
return this;
}
@Override
public Builder options(BuilderConfiguration options) {
this.options = options;
return this;
}
@Override
public RequestMappingInfo build() {
return new RequestMappingInfo(this.name, this.patternsCondition,
this.methodsCondition, this.paramsCondition, this.headersCondition,
this.consumesCondition, this.producesCondition,
this.customConditionHolder, this.options);
}
}
/**
* Container for configuration options used for request mapping purposes.
* Such configuration is required to create RequestMappingInfo instances but
......
/*
* Copyright 2002-2020 the original author or authors.
* Copyright 2002-2021 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
......@@ -38,6 +38,7 @@ import org.springframework.web.util.pattern.PatternParseException;
import static java.util.Arrays.asList;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
import static org.springframework.web.bind.annotation.RequestMethod.GET;
import static org.springframework.web.reactive.result.method.RequestMappingInfo.paths;
/**
......@@ -292,11 +293,10 @@ public class RequestMappingInfoTests {
@Test
@Disabled
public void preFlightRequest() throws Exception {
public void preFlightRequest() {
MockServerWebExchange exchange = MockServerWebExchange.from(MockServerHttpRequest.options("/foo")
.header("Origin", "https://domain.com")
.header(HttpHeaders.ACCESS_CONTROL_REQUEST_HEADERS, "POST")
);
.header(HttpHeaders.ACCESS_CONTROL_REQUEST_HEADERS, "POST"));
RequestMappingInfo info = paths("/foo").methods(RequestMethod.POST).build();
RequestMappingInfo match = info.getMatchingCondition(exchange);
......@@ -307,4 +307,26 @@ public class RequestMappingInfoTests {
assertThat(match).as("Pre-flight should match the ACCESS_CONTROL_REQUEST_METHOD").isNull();
}
@Test
void mutate() {
RequestMappingInfo.BuilderConfiguration options = new RequestMappingInfo.BuilderConfiguration();
options.setPatternParser(new PathPatternParser());
RequestMappingInfo info1 = RequestMappingInfo.paths("/foo")
.methods(GET).headers("h1=hv1").params("q1=qv1")
.consumes("application/json").produces("application/json")
.mappingName("testMapping").options(options)
.build();
RequestMappingInfo info2 = info1.mutate().produces("application/hal+json").build();
assertThat(info2.getName()).isEqualTo(info1.getName());
assertThat(info2.getPatternsCondition()).isEqualTo(info1.getPatternsCondition());
assertThat(info2.getHeadersCondition()).isEqualTo(info1.getHeadersCondition());
assertThat(info2.getParamsCondition()).isEqualTo(info1.getParamsCondition());
assertThat(info2.getConsumesCondition()).isEqualTo(info1.getConsumesCondition());
assertThat(info2.getProducesCondition().getProducibleMediaTypes())
.containsOnly(MediaType.parseMediaType("application/hal+json"));
}
}
/*
* Copyright 2002-2020 the original author or authors.
* Copyright 2002-2021 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
......@@ -105,6 +105,8 @@ public final class RequestMappingInfo implements RequestCondition<RequestMapping
private final int hashCode;
private final BuilderConfiguration options;
/**
* Full constructor with a mapping name.
......@@ -124,7 +126,8 @@ public final class RequestMappingInfo implements RequestCondition<RequestMapping
(headers != null ? headers : EMPTY_HEADERS),
(consumes != null ? consumes : EMPTY_CONSUMES),
(produces != null ? produces : EMPTY_PRODUCES),
(custom != null ? new RequestConditionHolder(custom) : EMPTY_CUSTOM));
(custom != null ? new RequestConditionHolder(custom) : EMPTY_CUSTOM),
new BuilderConfiguration());
}
/**
......@@ -156,7 +159,8 @@ public final class RequestMappingInfo implements RequestCondition<RequestMapping
@Nullable PatternsRequestCondition patternsCondition,
RequestMethodsRequestCondition methodsCondition, ParamsRequestCondition paramsCondition,
HeadersRequestCondition headersCondition, ConsumesRequestCondition consumesCondition,
ProducesRequestCondition producesCondition, RequestConditionHolder customCondition) {
ProducesRequestCondition producesCondition, RequestConditionHolder customCondition,
BuilderConfiguration options) {
Assert.isTrue(pathPatternsCondition != null || patternsCondition != null,
"Neither PathPatterns nor String patterns condition");
......@@ -170,6 +174,7 @@ public final class RequestMappingInfo implements RequestCondition<RequestMapping
this.consumesCondition = consumesCondition;
this.producesCondition = producesCondition;
this.customConditionHolder = customCondition;
this.options = options;
this.hashCode = calculateHashCode(
this.pathPatternsCondition, this.patternsCondition,
......@@ -307,9 +312,11 @@ public final class RequestMappingInfo implements RequestCondition<RequestMapping
* @since 5.3
*/
public RequestMappingInfo addCustomCondition(RequestCondition<?> customCondition) {
return new RequestMappingInfo(this.name, this.pathPatternsCondition, this.patternsCondition,
return new RequestMappingInfo(this.name,
this.pathPatternsCondition, this.patternsCondition,
this.methodsCondition, this.paramsCondition, this.headersCondition,
this.consumesCondition, this.producesCondition, new RequestConditionHolder(customCondition));
this.consumesCondition, this.producesCondition,
new RequestConditionHolder(customCondition), this.options);
}
/**
......@@ -337,8 +344,8 @@ public final class RequestMappingInfo implements RequestCondition<RequestMapping
ProducesRequestCondition produces = this.producesCondition.combine(other.producesCondition);
RequestConditionHolder custom = this.customConditionHolder.combine(other.customConditionHolder);
return new RequestMappingInfo(
name, pathPatterns, patterns, methods, params, headers, consumes, produces, custom);
return new RequestMappingInfo(name, pathPatterns, patterns,
methods, params, headers, consumes, produces, custom, this.options);
}
@Nullable
......@@ -405,8 +412,8 @@ public final class RequestMappingInfo implements RequestCondition<RequestMapping
if (custom == null) {
return null;
}
return new RequestMappingInfo(
this.name, pathPatterns, patterns, methods, params, headers, consumes, produces, custom);
return new RequestMappingInfo(this.name, pathPatterns, patterns,
methods, params, headers, consumes, produces, custom, this.options);
}
/**
......@@ -523,6 +530,15 @@ public final class RequestMappingInfo implements RequestCondition<RequestMapping
return builder.toString();
}
/**
* Return a builder to create a new RequestMappingInfo by modifying this one.
* @return a builder to create a new, modified instance
* @since 5.3.4
*/
public Builder mutate() {
return new MutateBuilder(this);
}
/**
* Create a new {@code RequestMappingInfo.Builder} with the given paths.
......@@ -719,7 +735,129 @@ public final class RequestMappingInfo implements RequestCondition<RequestMapping
ObjectUtils.isEmpty(this.produces) && !this.hasAccept ?
EMPTY_PRODUCES : new ProducesRequestCondition(this.produces, this.headers, manager),
this.customCondition != null ?
new RequestConditionHolder(this.customCondition) : EMPTY_CUSTOM);
new RequestConditionHolder(this.customCondition) : EMPTY_CUSTOM,
this.options);
}
}
private static class MutateBuilder implements Builder {
@Nullable
private String name;
@Nullable
private PathPatternsRequestCondition pathPatternsCondition;
@Nullable
private PatternsRequestCondition patternsCondition;
private RequestMethodsRequestCondition methodsCondition;
private ParamsRequestCondition paramsCondition;
private HeadersRequestCondition headersCondition;
private ConsumesRequestCondition consumesCondition;
private ProducesRequestCondition producesCondition;
private RequestConditionHolder customConditionHolder;
private BuilderConfiguration options;
public MutateBuilder(RequestMappingInfo other) {
this.name = other.name;
this.pathPatternsCondition = other.pathPatternsCondition;
this.patternsCondition = other.patternsCondition;
this.methodsCondition = other.methodsCondition;
this.paramsCondition = other.paramsCondition;
this.headersCondition = other.headersCondition;
this.consumesCondition = other.consumesCondition;
this.producesCondition = other.producesCondition;
this.customConditionHolder = other.customConditionHolder;
this.options = other.options;
}
@Override
@SuppressWarnings("deprecation")
public Builder paths(String... paths) {
if (this.options.patternParser != null) {
this.pathPatternsCondition = (ObjectUtils.isEmpty(paths) ?
EMPTY_PATH_PATTERNS : new PathPatternsRequestCondition(this.options.patternParser, paths));
}
else {
this.patternsCondition = (ObjectUtils.isEmpty(paths) ?
EMPTY_PATTERNS :
new PatternsRequestCondition(
paths, null, this.options.getPathMatcher(),
this.options.useSuffixPatternMatch(), this.options.useTrailingSlashMatch(),
this.options.getFileExtensions()));
}
return this;
}
@Override
public Builder methods(RequestMethod... methods) {
this.methodsCondition = (ObjectUtils.isEmpty(methods) ?
EMPTY_REQUEST_METHODS : new RequestMethodsRequestCondition(methods));
return this;
}
@Override
public Builder params(String... params) {
this.paramsCondition = (ObjectUtils.isEmpty(params) ?
EMPTY_PARAMS : new ParamsRequestCondition(params));
return this;
}
@Override
public Builder headers(String... headers) {
this.headersCondition = (ObjectUtils.isEmpty(headers) ?
EMPTY_HEADERS : new HeadersRequestCondition(headers));
return this;
}
@Override
public Builder consumes(String... consumes) {
this.consumesCondition = (ObjectUtils.isEmpty(consumes) ?
EMPTY_CONSUMES : new ConsumesRequestCondition(consumes));
return this;
}
@Override
public Builder produces(String... produces) {
this.producesCondition = (ObjectUtils.isEmpty(produces) ?
EMPTY_PRODUCES :
new ProducesRequestCondition(produces, null, this.options.getContentNegotiationManager()));
return this;
}
@Override
public Builder mappingName(String name) {
this.name = name;
return this;
}
@Override
public Builder customCondition(RequestCondition<?> condition) {
this.customConditionHolder = new RequestConditionHolder(condition);
return this;
}
@Override
public Builder options(BuilderConfiguration options) {
this.options = options;
return this;
}
@Override
public RequestMappingInfo build() {
return new RequestMappingInfo(this.name,
this.pathPatternsCondition, this.patternsCondition,
this.methodsCondition, this.paramsCondition, this.headersCondition,
this.consumesCondition, this.producesCondition,
this.customConditionHolder, this.options);
}
}
......
/*
* Copyright 2002-2020 the original author or authors.
* Copyright 2002-2021 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
......@@ -26,11 +26,11 @@ import javax.servlet.http.HttpServletRequest;
import org.junit.jupiter.api.Test;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.servlet.handler.PathPatternsParameterizedTest;
import org.springframework.web.servlet.handler.PathPatternsTestUtils;
import org.springframework.web.testfixture.servlet.MockHttpServletRequest;
import org.springframework.web.util.UrlPathHelper;
import org.springframework.web.util.pattern.PathPatternParser;
import static java.util.Arrays.asList;
......@@ -108,7 +108,6 @@ class RequestMappingInfoTests {
void matchParamsCondition() {
MockHttpServletRequest request = PathPatternsTestUtils.initRequest("GET", "/foo", false);
request.setParameter("foo", "bar");
UrlPathHelper.defaultInstance.resolveAndCacheLookupPath(request);
RequestMappingInfo info = RequestMappingInfo.paths("/foo").params("foo=bar").build();
RequestMappingInfo match = info.getMatchingCondition(request);
......@@ -125,7 +124,6 @@ class RequestMappingInfoTests {
void matchHeadersCondition() {
MockHttpServletRequest request = PathPatternsTestUtils.initRequest("GET", "/foo", false);
request.addHeader("foo", "bar");
UrlPathHelper.defaultInstance.resolveAndCacheLookupPath(request);
RequestMappingInfo info = RequestMappingInfo.paths("/foo").headers("foo=bar").build();
RequestMappingInfo match = info.getMatchingCondition(request);
......@@ -142,7 +140,6 @@ class RequestMappingInfoTests {
void matchConsumesCondition() {
MockHttpServletRequest request = PathPatternsTestUtils.initRequest("GET", "/foo", false);
request.setContentType("text/plain");
UrlPathHelper.defaultInstance.resolveAndCacheLookupPath(request);
RequestMappingInfo info = RequestMappingInfo.paths("/foo").consumes("text/plain").build();
RequestMappingInfo match = info.getMatchingCondition(request);
......@@ -159,7 +156,6 @@ class RequestMappingInfoTests {
void matchProducesCondition() {
MockHttpServletRequest request = PathPatternsTestUtils.initRequest("GET", "/foo", false);
request.addHeader("Accept", "text/plain");
UrlPathHelper.defaultInstance.resolveAndCacheLookupPath(request);
RequestMappingInfo info = RequestMappingInfo.paths("/foo").produces("text/plain").build();
RequestMappingInfo match = info.getMatchingCondition(request);
......@@ -176,7 +172,6 @@ class RequestMappingInfoTests {
void matchCustomCondition() {
MockHttpServletRequest request = PathPatternsTestUtils.initRequest("GET", "/foo", false);
request.setParameter("foo", "bar");
UrlPathHelper.defaultInstance.resolveAndCacheLookupPath(request);
RequestMappingInfo info = RequestMappingInfo.paths("/foo").params("foo=bar").build();
RequestMappingInfo match = info.getMatchingCondition(request);
......@@ -196,7 +191,6 @@ class RequestMappingInfoTests {
RequestMappingInfo oneMethodOneParam = RequestMappingInfo.paths().methods(GET).params("foo").build();
MockHttpServletRequest request = PathPatternsTestUtils.initRequest("GET", "/", false);
UrlPathHelper.defaultInstance.resolveAndCacheLookupPath(request);
Comparator<RequestMappingInfo> comparator = (info, otherInfo) -> info.compareTo(otherInfo, request);
List<RequestMappingInfo> list = asList(noMethods, oneMethod, oneMethodOneParam);
......@@ -317,4 +311,27 @@ class RequestMappingInfoTests {
assertThat(match).as("Pre-flight should match the ACCESS_CONTROL_REQUEST_METHOD").isNull();
}
@Test
void mutate() {
RequestMappingInfo.BuilderConfiguration options = new RequestMappingInfo.BuilderConfiguration();
options.setPatternParser(new PathPatternParser());
RequestMappingInfo info1 = RequestMappingInfo.paths("/foo")
.methods(GET).headers("h1=hv1").params("q1=qv1")
.consumes("application/json").produces("application/json")
.mappingName("testMapping").options(options)
.build();
RequestMappingInfo info2 = info1.mutate().produces("application/hal+json").build();
assertThat(info2.getName()).isEqualTo(info1.getName());
assertThat(info2.getPatternsCondition()).isNull();
assertThat(info2.getPathPatternsCondition()).isEqualTo(info1.getPathPatternsCondition());
assertThat(info2.getHeadersCondition()).isEqualTo(info1.getHeadersCondition());
assertThat(info2.getParamsCondition()).isEqualTo(info1.getParamsCondition());
assertThat(info2.getConsumesCondition()).isEqualTo(info1.getConsumesCondition());
assertThat(info2.getProducesCondition().getProducibleMediaTypes())
.containsOnly(MediaType.parseMediaType("application/hal+json"));
}
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册