Browse Source

Fine-tuned assertions and related polishing

pull/1820/head
Juergen Hoeller 8 years ago
parent
commit
c9f488363d
  1. 2
      spring-expression/src/main/java/org/springframework/expression/spel/standard/Tokenizer.java
  2. 2
      spring-web/src/main/java/org/springframework/http/HttpHeaders.java
  3. 4
      spring-webflux/src/main/java/org/springframework/web/reactive/function/client/ClientRequest.java
  4. 42
      spring-webflux/src/main/java/org/springframework/web/reactive/function/client/DefaultClientRequestBuilder.java
  5. 10
      spring-webflux/src/main/java/org/springframework/web/reactive/function/client/DefaultClientResponseBuilder.java
  6. 4
      spring-webflux/src/main/java/org/springframework/web/reactive/function/client/DefaultWebClientBuilder.java
  7. 1
      spring-webflux/src/main/java/org/springframework/web/reactive/function/server/DefaultEntityResponseBuilder.java
  8. 1
      spring-webflux/src/main/java/org/springframework/web/reactive/function/server/DefaultRenderingResponseBuilder.java
  9. 6
      spring-webflux/src/main/java/org/springframework/web/reactive/function/server/DefaultServerRequest.java
  10. 71
      spring-webflux/src/main/java/org/springframework/web/reactive/function/server/DefaultServerRequestBuilder.java
  11. 46
      spring-webflux/src/main/java/org/springframework/web/reactive/function/server/DefaultServerResponseBuilder.java
  12. 18
      spring-webflux/src/main/java/org/springframework/web/reactive/function/server/ServerRequest.java
  13. 2
      spring-webmvc/src/test/java/org/springframework/web/servlet/mvc/method/annotation/ResponseEntityExceptionHandlerTests.java

2
spring-expression/src/main/java/org/springframework/expression/spel/standard/Tokenizer.java

@ -265,7 +265,7 @@ class Tokenizer {
raiseParseException(this.pos, SpelMessage.UNEXPECTED_ESCAPE_CHAR); raiseParseException(this.pos, SpelMessage.UNEXPECTED_ESCAPE_CHAR);
break; break;
default: default:
throw new IllegalStateException("Cannot handle ('" + ch + "')"); throw new IllegalStateException("Cannot handle (" + (int) ch + ") '" + ch + "'");
} }
} }
} }

2
spring-web/src/main/java/org/springframework/http/HttpHeaders.java

@ -414,7 +414,6 @@ public class HttpHeaders implements MultiValueMap<String, String>, Serializable
* Private constructor that can create read-only {@code HttpHeader} instances. * Private constructor that can create read-only {@code HttpHeader} instances.
*/ */
private HttpHeaders(Map<String, List<String>> headers, boolean readOnly) { private HttpHeaders(Map<String, List<String>> headers, boolean readOnly) {
Assert.notNull(headers, "'headers' must not be null");
if (readOnly) { if (readOnly) {
Map<String, List<String>> map = new LinkedCaseInsensitiveMap<>(headers.size(), Locale.ENGLISH); Map<String, List<String>> map = new LinkedCaseInsensitiveMap<>(headers.size(), Locale.ENGLISH);
headers.forEach((key, valueList) -> map.put(key, Collections.unmodifiableList(valueList))); headers.forEach((key, valueList) -> map.put(key, Collections.unmodifiableList(valueList)));
@ -1556,6 +1555,7 @@ public class HttpHeaders implements MultiValueMap<String, String>, Serializable
* Return a {@code HttpHeaders} object that can only be read, not written to. * Return a {@code HttpHeaders} object that can only be read, not written to.
*/ */
public static HttpHeaders readOnlyHttpHeaders(HttpHeaders headers) { public static HttpHeaders readOnlyHttpHeaders(HttpHeaders headers) {
Assert.notNull(headers, "HttpHeaders must not be null");
return (headers.readOnly ? headers : new HttpHeaders(headers, true)); return (headers.readOnly ? headers : new HttpHeaders(headers, true));
} }

4
spring-webflux/src/main/java/org/springframework/web/reactive/function/client/ClientRequest.java

@ -114,7 +114,7 @@ public interface ClientRequest {
/** /**
* Create a builder with the given method and url. * Create a builder with the given method and url.
* @param method the HTTP method (GET, POST, etc) * @param method the HTTP method (GET, POST, etc)
* @param url the URL * @param url the url (as a URI instance)
* @return the created builder * @return the created builder
* @deprecated in favor of {@link #create(HttpMethod, URI)} * @deprecated in favor of {@link #create(HttpMethod, URI)}
*/ */
@ -126,7 +126,7 @@ public interface ClientRequest {
/** /**
* Create a request builder with the given method and url. * Create a request builder with the given method and url.
* @param method the HTTP method (GET, POST, etc) * @param method the HTTP method (GET, POST, etc)
* @param url the URL * @param url the url (as a URI instance)
* @return the created builder * @return the created builder
*/ */
static Builder create(HttpMethod method, URI url) { static Builder create(HttpMethod method, URI url) {

42
spring-webflux/src/main/java/org/springframework/web/reactive/function/client/DefaultClientRequestBuilder.java

@ -49,28 +49,30 @@ import org.springframework.web.reactive.function.BodyInserters;
*/ */
final class DefaultClientRequestBuilder implements ClientRequest.Builder { final class DefaultClientRequestBuilder implements ClientRequest.Builder {
private HttpMethod method;
private URI url;
private final HttpHeaders headers = new HttpHeaders(); private final HttpHeaders headers = new HttpHeaders();
private final MultiValueMap<String, String> cookies = new LinkedMultiValueMap<>(); private final MultiValueMap<String, String> cookies = new LinkedMultiValueMap<>();
private final Map<String, Object> attributes = new LinkedHashMap<>(); private final Map<String, Object> attributes = new LinkedHashMap<>();
private HttpMethod method; private BodyInserter<?, ? super ClientHttpRequest> body = BodyInserters.empty();
private URI url;
private BodyInserter<?, ? super ClientHttpRequest> inserter = BodyInserters.empty();
public DefaultClientRequestBuilder(HttpMethod method, URI url) { public DefaultClientRequestBuilder(HttpMethod method, URI url) {
method(method); Assert.notNull(method, "HttpMethod must not be null");
url(url); Assert.notNull(url, "URI must not be null");
this.method = method;
this.url = url;
} }
public DefaultClientRequestBuilder(ClientRequest other) { public DefaultClientRequestBuilder(ClientRequest other) {
Assert.notNull(other, "ClientRequest must not be null"); Assert.notNull(other, "ClientRequest must not be null");
method(other.method()); this.method = other.method();
url(other.url()); this.url = other.url();
headers(headers -> headers.addAll(other.headers())); headers(headers -> headers.addAll(other.headers()));
cookies(cookies -> cookies.addAll(other.cookies())); cookies(cookies -> cookies.addAll(other.cookies()));
attributes(attributes -> attributes.putAll(other.attributes())); attributes(attributes -> attributes.putAll(other.attributes()));
@ -125,7 +127,7 @@ final class DefaultClientRequestBuilder implements ClientRequest.Builder {
Assert.notNull(publisher, "'publisher' must not be null"); Assert.notNull(publisher, "'publisher' must not be null");
Assert.notNull(elementClass, "'elementClass' must not be null"); Assert.notNull(elementClass, "'elementClass' must not be null");
this.inserter = BodyInserters.fromPublisher(publisher, elementClass); this.body = BodyInserters.fromPublisher(publisher, elementClass);
return this; return this;
} }
@ -136,7 +138,7 @@ final class DefaultClientRequestBuilder implements ClientRequest.Builder {
Assert.notNull(publisher, "'publisher' must not be null"); Assert.notNull(publisher, "'publisher' must not be null");
Assert.notNull(typeReference, "'typeReference' must not be null"); Assert.notNull(typeReference, "'typeReference' must not be null");
this.inserter = BodyInserters.fromPublisher(publisher, typeReference); this.body = BodyInserters.fromPublisher(publisher, typeReference);
return this; return this;
} }
@ -154,14 +156,13 @@ final class DefaultClientRequestBuilder implements ClientRequest.Builder {
@Override @Override
public ClientRequest.Builder body(BodyInserter<?, ? super ClientHttpRequest> inserter) { public ClientRequest.Builder body(BodyInserter<?, ? super ClientHttpRequest> inserter) {
this.inserter = inserter; this.body = inserter;
return this; return this;
} }
@Override @Override
public ClientRequest build() { public ClientRequest build() {
return new BodyInserterRequest(this.method, this.url, this.headers, this.cookies, return new BodyInserterRequest(this.method, this.url, this.headers, this.cookies, this.body, this.attributes);
this.inserter, this.attributes);
} }
@ -175,20 +176,19 @@ final class DefaultClientRequestBuilder implements ClientRequest.Builder {
private final MultiValueMap<String, String> cookies; private final MultiValueMap<String, String> cookies;
private final BodyInserter<?, ? super ClientHttpRequest> inserter; private final BodyInserter<?, ? super ClientHttpRequest> body;
private final Map<String, Object> attributes; private final Map<String, Object> attributes;
public BodyInserterRequest(HttpMethod method, URI url, HttpHeaders headers, public BodyInserterRequest(HttpMethod method, URI url, HttpHeaders headers,
MultiValueMap<String, String> cookies, MultiValueMap<String, String> cookies, BodyInserter<?, ? super ClientHttpRequest> body,
BodyInserter<?, ? super ClientHttpRequest> inserter,
Map<String, Object> attributes) { Map<String, Object> attributes) {
this.method = method; this.method = method;
this.url = url; this.url = url;
this.headers = HttpHeaders.readOnlyHttpHeaders(headers); this.headers = HttpHeaders.readOnlyHttpHeaders(headers);
this.cookies = CollectionUtils.unmodifiableMultiValueMap(cookies); this.cookies = CollectionUtils.unmodifiableMultiValueMap(cookies);
this.inserter = inserter; this.body = body;
this.attributes = Collections.unmodifiableMap(attributes); this.attributes = Collections.unmodifiableMap(attributes);
} }
@ -214,7 +214,7 @@ final class DefaultClientRequestBuilder implements ClientRequest.Builder {
@Override @Override
public BodyInserter<?, ? super ClientHttpRequest> body() { public BodyInserter<?, ? super ClientHttpRequest> body() {
return this.inserter; return this.body;
} }
@Override @Override
@ -240,17 +240,15 @@ final class DefaultClientRequestBuilder implements ClientRequest.Builder {
})); }));
} }
return this.inserter.insert(request, new BodyInserter.Context() { return this.body.insert(request, new BodyInserter.Context() {
@Override @Override
public List<HttpMessageWriter<?>> messageWriters() { public List<HttpMessageWriter<?>> messageWriters() {
return strategies.messageWriters(); return strategies.messageWriters();
} }
@Override @Override
public Optional<ServerHttpRequest> serverRequest() { public Optional<ServerHttpRequest> serverRequest() {
return Optional.empty(); return Optional.empty();
} }
@Override @Override
public Map<String, Object> hints() { public Map<String, Object> hints() {
return Collections.emptyMap(); return Collections.emptyMap();

10
spring-webflux/src/main/java/org/springframework/web/reactive/function/client/DefaultClientResponseBuilder.java

@ -42,16 +42,16 @@ import org.springframework.util.MultiValueMap;
*/ */
final class DefaultClientResponseBuilder implements ClientResponse.Builder { final class DefaultClientResponseBuilder implements ClientResponse.Builder {
private ExchangeStrategies strategies;
private HttpStatus statusCode = HttpStatus.OK;
private final HttpHeaders headers = new HttpHeaders(); private final HttpHeaders headers = new HttpHeaders();
private final MultiValueMap<String, ResponseCookie> cookies = new LinkedMultiValueMap<>(); private final MultiValueMap<String, ResponseCookie> cookies = new LinkedMultiValueMap<>();
private HttpStatus statusCode = HttpStatus.OK;
private Flux<DataBuffer> body = Flux.empty(); private Flux<DataBuffer> body = Flux.empty();
private ExchangeStrategies strategies;
public DefaultClientResponseBuilder(ExchangeStrategies strategies) { public DefaultClientResponseBuilder(ExchangeStrategies strategies) {
Assert.notNull(strategies, "ExchangeStrategies must not be null"); Assert.notNull(strategies, "ExchangeStrategies must not be null");
@ -84,7 +84,6 @@ final class DefaultClientResponseBuilder implements ClientResponse.Builder {
@Override @Override
public ClientResponse.Builder headers(Consumer<HttpHeaders> headersConsumer) { public ClientResponse.Builder headers(Consumer<HttpHeaders> headersConsumer) {
Assert.notNull(headersConsumer, "Consumer must not be null");
headersConsumer.accept(this.headers); headersConsumer.accept(this.headers);
return this; return this;
} }
@ -99,7 +98,6 @@ final class DefaultClientResponseBuilder implements ClientResponse.Builder {
@Override @Override
public ClientResponse.Builder cookies(Consumer<MultiValueMap<String, ResponseCookie>> cookiesConsumer) { public ClientResponse.Builder cookies(Consumer<MultiValueMap<String, ResponseCookie>> cookiesConsumer) {
Assert.notNull(cookiesConsumer, "Consumer must not be null");
cookiesConsumer.accept(this.cookies); cookiesConsumer.accept(this.cookies);
return this; return this;
} }

4
spring-webflux/src/main/java/org/springframework/web/reactive/function/client/DefaultWebClientBuilder.java

@ -208,9 +208,7 @@ final class DefaultWebClientBuilder implements WebClient.Builder {
private static @Nullable HttpHeaders unmodifiableCopy(@Nullable HttpHeaders original) { private static @Nullable HttpHeaders unmodifiableCopy(@Nullable HttpHeaders original) {
if (original != null) { if (original != null) {
HttpHeaders copy = new HttpHeaders(); return HttpHeaders.readOnlyHttpHeaders(original);
copy.putAll(original);
return HttpHeaders.readOnlyHttpHeaders(copy);
} }
else { else {
return null; return null;

1
spring-webflux/src/main/java/org/springframework/web/reactive/function/server/DefaultEntityResponseBuilder.java

@ -96,7 +96,6 @@ class DefaultEntityResponseBuilder<T> implements EntityResponse.Builder<T> {
@Override @Override
public EntityResponse.Builder<T> cookies(Consumer<MultiValueMap<String, ResponseCookie>> cookiesConsumer) { public EntityResponse.Builder<T> cookies(Consumer<MultiValueMap<String, ResponseCookie>> cookiesConsumer) {
Assert.notNull(cookiesConsumer, "Consumer must not be null");
cookiesConsumer.accept(this.cookies); cookiesConsumer.accept(this.cookies);
return this; return this;
} }

1
spring-webflux/src/main/java/org/springframework/web/reactive/function/server/DefaultRenderingResponseBuilder.java

@ -99,7 +99,6 @@ final class DefaultRenderingResponseBuilder implements RenderingResponse.Builder
@Override @Override
public RenderingResponse.Builder cookies(Consumer<MultiValueMap<String, ResponseCookie>> cookiesConsumer) { public RenderingResponse.Builder cookies(Consumer<MultiValueMap<String, ResponseCookie>> cookiesConsumer) {
Assert.notNull(cookiesConsumer, "Consumer must not be null");
cookiesConsumer.accept(this.cookies); cookiesConsumer.accept(this.cookies);
return this; return this;
} }

6
spring-webflux/src/main/java/org/springframework/web/reactive/function/server/DefaultServerRequest.java

@ -76,14 +76,10 @@ class DefaultServerRequest implements ServerRequest {
DefaultServerRequest(ServerWebExchange exchange, List<HttpMessageReader<?>> messageReaders) { DefaultServerRequest(ServerWebExchange exchange, List<HttpMessageReader<?>> messageReaders) {
this.exchange = exchange; this.exchange = exchange;
this.messageReaders = unmodifiableCopy(messageReaders); this.messageReaders = Collections.unmodifiableList(new ArrayList<>(messageReaders));
this.headers = new DefaultHeaders(); this.headers = new DefaultHeaders();
} }
private static <T> List<T> unmodifiableCopy(List<? extends T> list) {
return Collections.unmodifiableList(new ArrayList<>(list));
}
@Override @Override
public String methodName() { public String methodName() {

71
spring-webflux/src/main/java/org/springframework/web/reactive/function/server/DefaultServerRequestBuilder.java

@ -67,37 +67,39 @@ import org.springframework.web.util.UriUtils;
*/ */
class DefaultServerRequestBuilder implements ServerRequest.Builder { class DefaultServerRequestBuilder implements ServerRequest.Builder {
private final HttpHeaders headers = new HttpHeaders();
private final MultiValueMap<String, HttpCookie> cookies = new LinkedMultiValueMap<>();
private final Map<String, Object> attributes = new LinkedHashMap<>();
private final List<HttpMessageReader<?>> messageReaders; private final List<HttpMessageReader<?>> messageReaders;
private ServerWebExchange exchange; private ServerWebExchange exchange;
private HttpMethod method = HttpMethod.GET; private String methodName;
@Nullable
private URI uri; private URI uri;
private final HttpHeaders headers = new HttpHeaders();
private final MultiValueMap<String, HttpCookie> cookies = new LinkedMultiValueMap<>();
private final Map<String, Object> attributes = new LinkedHashMap<>();
private Flux<DataBuffer> body = Flux.empty(); private Flux<DataBuffer> body = Flux.empty();
public DefaultServerRequestBuilder(ServerRequest other) { public DefaultServerRequestBuilder(ServerRequest other) {
Assert.notNull(other, "ServerRequest must not be null"); Assert.notNull(other, "ServerRequest must not be null");
this.messageReaders = other.messageReaders(); this.messageReaders = other.messageReaders();
this.exchange = other.exchange(); this.exchange = other.exchange();
method(other.method()); this.methodName = other.methodName();
uri(other.uri()); this.uri = other.uri();
headers(headers -> headers.addAll(other.headers().asHttpHeaders())); headers(headers -> headers.addAll(other.headers().asHttpHeaders()));
cookies(cookies -> cookies.addAll(other.cookies())); cookies(cookies -> cookies.addAll(other.cookies()));
attributes(attributes -> attributes.putAll(other.attributes()));
} }
@Override @Override
public ServerRequest.Builder method(HttpMethod method) { public ServerRequest.Builder method(HttpMethod method) {
Assert.notNull(method, "'method' must not be null"); Assert.notNull(method, "'method' must not be null");
this.method = method; this.methodName = method.name();
return this; return this;
} }
@ -118,7 +120,6 @@ class DefaultServerRequestBuilder implements ServerRequest.Builder {
@Override @Override
public ServerRequest.Builder headers(Consumer<HttpHeaders> headersConsumer) { public ServerRequest.Builder headers(Consumer<HttpHeaders> headersConsumer) {
Assert.notNull(headersConsumer, "'headersConsumer' must not be null");
headersConsumer.accept(this.headers); headersConsumer.accept(this.headers);
return this; return this;
} }
@ -132,10 +133,7 @@ class DefaultServerRequestBuilder implements ServerRequest.Builder {
} }
@Override @Override
public ServerRequest.Builder cookies( public ServerRequest.Builder cookies(Consumer<MultiValueMap<String, HttpCookie>> cookiesConsumer) {
Consumer<MultiValueMap<String, HttpCookie>> cookiesConsumer) {
Assert.notNull(cookiesConsumer, "'cookiesConsumer' must not be null");
cookiesConsumer.accept(this.cookies); cookiesConsumer.accept(this.cookies);
return this; return this;
} }
@ -174,26 +172,25 @@ class DefaultServerRequestBuilder implements ServerRequest.Builder {
@Override @Override
public ServerRequest.Builder attributes(Consumer<Map<String, Object>> attributesConsumer) { public ServerRequest.Builder attributes(Consumer<Map<String, Object>> attributesConsumer) {
Assert.notNull(attributesConsumer, "'attributesConsumer' must not be null");
attributesConsumer.accept(this.attributes); attributesConsumer.accept(this.attributes);
return this; return this;
} }
@Override @Override
public ServerRequest build() { public ServerRequest build() {
ServerHttpRequest serverHttpRequest = new BuiltServerHttpRequest(this.method, this.uri, ServerHttpRequest serverHttpRequest = new BuiltServerHttpRequest(
this.headers, this.cookies, this.body); this.methodName, this.uri, this.headers, this.cookies, this.body);
ServerWebExchange exchange = new DelegatingServerWebExchange(serverHttpRequest, ServerWebExchange exchange = new DelegatingServerWebExchange(
this.exchange, this.messageReaders); serverHttpRequest, this.exchange, this.messageReaders);
return new DefaultServerRequest(exchange, this.messageReaders); return new DefaultServerRequest(exchange, this.messageReaders);
} }
private static class BuiltServerHttpRequest implements ServerHttpRequest { private static class BuiltServerHttpRequest implements ServerHttpRequest {
private static final Pattern QUERY_PATTERN = Pattern.compile("([^&=]+)(=?)([^&]+)?"); private static final Pattern QUERY_PATTERN = Pattern.compile("([^&=]+)(=?)([^&]+)?");
private final String method;
private final HttpMethod method;
private final URI uri; private final URI uri;
@ -207,10 +204,9 @@ class DefaultServerRequestBuilder implements ServerRequest.Builder {
private final Flux<DataBuffer> body; private final Flux<DataBuffer> body;
public BuiltServerHttpRequest(HttpMethod method, URI uri, public BuiltServerHttpRequest(String method, URI uri, HttpHeaders headers,
HttpHeaders headers, MultiValueMap<String, HttpCookie> cookies, Flux<DataBuffer> body) {
MultiValueMap<String, HttpCookie> cookies,
Flux<DataBuffer> body) {
this.method = method; this.method = method;
this.uri = uri; this.uri = uri;
this.path = RequestPath.parse(uri, null); this.path = RequestPath.parse(uri, null);
@ -245,15 +241,9 @@ class DefaultServerRequestBuilder implements ServerRequest.Builder {
return queryParams; return queryParams;
} }
@Nullable
@Override
public HttpMethod getMethod() {
return this.method;
}
@Override @Override
public String getMethodValue() { public String getMethodValue() {
return this.method.name(); return this.method;
} }
@Override @Override
@ -287,6 +277,7 @@ class DefaultServerRequestBuilder implements ServerRequest.Builder {
} }
} }
private static class DelegatingServerWebExchange implements ServerWebExchange { private static class DelegatingServerWebExchange implements ServerWebExchange {
private static final ResolvableType FORM_DATA_TYPE = private static final ResolvableType FORM_DATA_TYPE =
@ -296,12 +287,10 @@ class DefaultServerRequestBuilder implements ServerRequest.Builder {
MultiValueMap.class, String.class, Part.class); MultiValueMap.class, String.class, Part.class);
private static final Mono<MultiValueMap<String, String>> EMPTY_FORM_DATA = private static final Mono<MultiValueMap<String, String>> EMPTY_FORM_DATA =
Mono.just(CollectionUtils.unmodifiableMultiValueMap(new LinkedMultiValueMap<String, String>(0))) Mono.just(CollectionUtils.unmodifiableMultiValueMap(new LinkedMultiValueMap<String, String>(0))).cache();
.cache();
private static final Mono<MultiValueMap<String, Part>> EMPTY_MULTIPART_DATA = private static final Mono<MultiValueMap<String, Part>> EMPTY_MULTIPART_DATA =
Mono.just(CollectionUtils.unmodifiableMultiValueMap(new LinkedMultiValueMap<String, Part>(0))) Mono.just(CollectionUtils.unmodifiableMultiValueMap(new LinkedMultiValueMap<String, Part>(0))).cache();
.cache();
private final ServerHttpRequest request; private final ServerHttpRequest request;
@ -311,8 +300,9 @@ class DefaultServerRequestBuilder implements ServerRequest.Builder {
private final Mono<MultiValueMap<String, Part>> multipartDataMono; private final Mono<MultiValueMap<String, Part>> multipartDataMono;
public DelegatingServerWebExchange(ServerHttpRequest request, ServerWebExchange delegate, public DelegatingServerWebExchange(
List<HttpMessageReader<?>> messageReaders) { ServerHttpRequest request, ServerWebExchange delegate, List<HttpMessageReader<?>> messageReaders) {
this.request = request; this.request = request;
this.delegate = delegate; this.delegate = delegate;
this.formDataMono = initFormData(request, messageReaders); this.formDataMono = initFormData(request, messageReaders);
@ -399,7 +389,6 @@ class DefaultServerRequestBuilder implements ServerRequest.Builder {
return this.delegate.getPrincipal(); return this.delegate.getPrincipal();
} }
@Override @Override
public LocaleContext getLocaleContext() { public LocaleContext getLocaleContext() {
return this.delegate.getLocaleContext(); return this.delegate.getLocaleContext();

46
spring-webflux/src/main/java/org/springframework/web/reactive/function/server/DefaultServerResponseBuilder.java

@ -97,7 +97,6 @@ class DefaultServerResponseBuilder implements ServerResponse.BodyBuilder {
@Override @Override
public ServerResponse.BodyBuilder headers(Consumer<HttpHeaders> headersConsumer) { public ServerResponse.BodyBuilder headers(Consumer<HttpHeaders> headersConsumer) {
Assert.notNull(headersConsumer, "Consumer must not be null");
headersConsumer.accept(this.headers); headersConsumer.accept(this.headers);
return this; return this;
} }
@ -111,7 +110,6 @@ class DefaultServerResponseBuilder implements ServerResponse.BodyBuilder {
@Override @Override
public ServerResponse.BodyBuilder cookies(Consumer<MultiValueMap<String, ResponseCookie>> cookiesConsumer) { public ServerResponse.BodyBuilder cookies(Consumer<MultiValueMap<String, ResponseCookie>> cookiesConsumer) {
Assert.notNull(cookiesConsumer, "Consumer must not be null");
cookiesConsumer.accept(this.cookies); cookiesConsumer.accept(this.cookies);
return this; return this;
} }
@ -201,9 +199,8 @@ class DefaultServerResponseBuilder implements ServerResponse.BodyBuilder {
public Mono<ServerResponse> build( public Mono<ServerResponse> build(
BiFunction<ServerWebExchange, ServerResponse.Context, Mono<Void>> writeFunction) { BiFunction<ServerWebExchange, ServerResponse.Context, Mono<Void>> writeFunction) {
Assert.notNull(writeFunction, "BiFunction must not be null");
return Mono.just( return Mono.just(
new WriterFunctionServerResponse(this.statusCode, this.headers, this.cookies, writeFunction)); new WriterFunctionResponse(this.statusCode, this.headers, this.cookies, writeFunction));
} }
@Override @Override
@ -250,15 +247,12 @@ class DefaultServerResponseBuilder implements ServerResponse.BodyBuilder {
@Override @Override
public Mono<ServerResponse> body(BodyInserter<?, ? super ServerHttpResponse> inserter) { public Mono<ServerResponse> body(BodyInserter<?, ? super ServerHttpResponse> inserter) {
Assert.notNull(inserter, "BodyInserter must not be null");
return Mono.just( return Mono.just(
new BodyInserterServerResponse<>(this.statusCode, this.headers, this.cookies, inserter, this.hints)); new BodyInserterResponse<>(this.statusCode, this.headers, this.cookies, inserter, this.hints));
} }
@Override @Override
public Mono<ServerResponse> render(String name, Object... modelAttributes) { public Mono<ServerResponse> render(String name, Object... modelAttributes) {
Assert.hasLength(name, "Name must not be empty");
return new DefaultRenderingResponseBuilder(name) return new DefaultRenderingResponseBuilder(name)
.headers(this.headers) .headers(this.headers)
.status(this.statusCode) .status(this.statusCode)
@ -269,8 +263,6 @@ class DefaultServerResponseBuilder implements ServerResponse.BodyBuilder {
@Override @Override
public Mono<ServerResponse> render(String name, Map<String, ?> model) { public Mono<ServerResponse> render(String name, Map<String, ?> model) {
Assert.hasLength(name, "Name must not be empty");
return new DefaultRenderingResponseBuilder(name) return new DefaultRenderingResponseBuilder(name)
.headers(this.headers) .headers(this.headers)
.status(this.statusCode) .status(this.statusCode)
@ -290,24 +282,12 @@ class DefaultServerResponseBuilder implements ServerResponse.BodyBuilder {
private final MultiValueMap<String, ResponseCookie> cookies; private final MultiValueMap<String, ResponseCookie> cookies;
protected AbstractServerResponse(int statusCode, HttpHeaders headers, protected AbstractServerResponse(
MultiValueMap<String, ResponseCookie> cookies) { int statusCode, HttpHeaders headers, MultiValueMap<String, ResponseCookie> cookies) {
this.statusCode = statusCode; this.statusCode = statusCode;
this.headers = readOnlyCopy(headers); this.headers = HttpHeaders.readOnlyHttpHeaders(headers);
this.cookies = readOnlyCopy(cookies); this.cookies = CollectionUtils.unmodifiableMultiValueMap(new LinkedMultiValueMap<>(cookies));
}
private static HttpHeaders readOnlyCopy(HttpHeaders headers) {
HttpHeaders copy = new HttpHeaders();
copy.putAll(headers);
return HttpHeaders.readOnlyHttpHeaders(copy);
}
private static <K, V> MultiValueMap<K,V> readOnlyCopy(MultiValueMap<K, V> map) {
MultiValueMap<K, V> copy = new LinkedMultiValueMap<>();
copy.putAll(map);
return CollectionUtils.unmodifiableMultiValueMap(copy);
} }
@Override @Override
@ -367,15 +347,16 @@ class DefaultServerResponseBuilder implements ServerResponse.BodyBuilder {
} }
private static final class WriterFunctionServerResponse extends AbstractServerResponse { private static final class WriterFunctionResponse extends AbstractServerResponse {
private final BiFunction<ServerWebExchange, Context, Mono<Void>> writeFunction; private final BiFunction<ServerWebExchange, Context, Mono<Void>> writeFunction;
public WriterFunctionServerResponse(int statusCode, HttpHeaders headers, public WriterFunctionResponse(int statusCode, HttpHeaders headers,
MultiValueMap<String, ResponseCookie> cookies, MultiValueMap<String, ResponseCookie> cookies,
BiFunction<ServerWebExchange, Context, Mono<Void>> writeFunction) { BiFunction<ServerWebExchange, Context, Mono<Void>> writeFunction) {
super(statusCode, headers, cookies); super(statusCode, headers, cookies);
Assert.notNull(writeFunction, "BiFunction must not be null");
this.writeFunction = writeFunction; this.writeFunction = writeFunction;
} }
@ -386,18 +367,19 @@ class DefaultServerResponseBuilder implements ServerResponse.BodyBuilder {
} }
private static final class BodyInserterServerResponse<T> extends AbstractServerResponse { private static final class BodyInserterResponse<T> extends AbstractServerResponse {
private final BodyInserter<T, ? super ServerHttpResponse> inserter; private final BodyInserter<T, ? super ServerHttpResponse> inserter;
private final Map<String, Object> hints; private final Map<String, Object> hints;
public BodyInserterServerResponse(int statusCode, HttpHeaders headers, public BodyInserterResponse(int statusCode, HttpHeaders headers,
MultiValueMap<String, ResponseCookie> cookies, MultiValueMap<String, ResponseCookie> cookies,
BodyInserter<T, ? super ServerHttpResponse> inserter, Map<String, Object> hints) { BodyInserter<T, ? super ServerHttpResponse> body, Map<String, Object> hints) {
super(statusCode, headers, cookies); super(statusCode, headers, cookies);
this.inserter = inserter; Assert.notNull(body, "BodyInserter must not be null");
this.inserter = body;
this.hints = hints; this.hints = hints;
} }

18
spring-webflux/src/main/java/org/springframework/web/reactive/function/server/ServerRequest.java

@ -43,7 +43,6 @@ import org.springframework.http.codec.multipart.Part;
import org.springframework.http.server.PathContainer; import org.springframework.http.server.PathContainer;
import org.springframework.http.server.reactive.ServerHttpRequest; import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.lang.Nullable; import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
import org.springframework.util.CollectionUtils; import org.springframework.util.CollectionUtils;
import org.springframework.util.MultiValueMap; import org.springframework.util.MultiValueMap;
import org.springframework.web.reactive.function.BodyExtractor; import org.springframework.web.reactive.function.BodyExtractor;
@ -125,6 +124,7 @@ public interface ServerRequest {
/** /**
* Return the readers used to convert the body of this request. * Return the readers used to convert the body of this request.
* @since 5.1
*/ */
List<HttpMessageReader<?>> messageReaders(); List<HttpMessageReader<?>> messageReaders();
@ -262,7 +262,6 @@ public interface ServerRequest {
/** /**
* Return the form data from the body of the request if the Content-Type is * Return the form data from the body of the request if the Content-Type is
* {@code "application/x-www-form-urlencoded"} or an empty map otherwise. * {@code "application/x-www-form-urlencoded"} or an empty map otherwise.
*
* <p><strong>Note:</strong> calling this method causes the request body to * <p><strong>Note:</strong> calling this method causes the request body to
* be read and parsed in full and the resulting {@code MultiValueMap} is * be read and parsed in full and the resulting {@code MultiValueMap} is
* cached so that this method is safe to call more than once. * cached so that this method is safe to call more than once.
@ -272,7 +271,6 @@ public interface ServerRequest {
/** /**
* Return the parts of a multipart request if the Content-Type is * Return the parts of a multipart request if the Content-Type is
* {@code "multipart/form-data"} or an empty map otherwise. * {@code "multipart/form-data"} or an empty map otherwise.
*
* <p><strong>Note:</strong> calling this method causes the request body to * <p><strong>Note:</strong> calling this method causes the request body to
* be read and parsed in full and the resulting {@code MultiValueMap} is * be read and parsed in full and the resulting {@code MultiValueMap} is
* cached so that this method is safe to call more than once. * cached so that this method is safe to call more than once.
@ -280,14 +278,14 @@ public interface ServerRequest {
Mono<MultiValueMap<String, Part>> multipartData(); Mono<MultiValueMap<String, Part>> multipartData();
/** /**
* Returns the web exchange that this request is based on. Manipulating the exchange directly, * Return the web exchange that this request is based on.
* instead of using the methods provided on {@code ServerRequest} and {@code ServerResponse}, * <p>Note: Manipulating the exchange directly (instead of using the methods provided on
* can lead to irregular results. * {@code ServerRequest} and {@code ServerResponse}) can lead to irregular results.
* * @since 5.1
* @return the web exchange
*/ */
ServerWebExchange exchange(); ServerWebExchange exchange();
// Static methods // Static methods
/** /**
@ -305,12 +303,13 @@ public interface ServerRequest {
* Create a builder with the status, headers, and cookies of the given request. * Create a builder with the status, headers, and cookies of the given request.
* @param other the response to copy the status, headers, and cookies from * @param other the response to copy the status, headers, and cookies from
* @return the created builder * @return the created builder
* @since 5.1
*/ */
static Builder from(ServerRequest other) { static Builder from(ServerRequest other) {
Assert.notNull(other, "'other' must not be null");
return new DefaultServerRequestBuilder(other); return new DefaultServerRequestBuilder(other);
} }
/** /**
* Represents the headers of the HTTP request. * Represents the headers of the HTTP request.
* @see ServerRequest#headers() * @see ServerRequest#headers()
@ -378,6 +377,7 @@ public interface ServerRequest {
/** /**
* Defines a builder for a request. * Defines a builder for a request.
* @since 5.1
*/ */
interface Builder { interface Builder {

2
spring-webmvc/src/test/java/org/springframework/web/servlet/mvc/method/annotation/ResponseEntityExceptionHandlerTests.java

@ -328,6 +328,8 @@ public class ResponseEntityExceptionHandlerTests {
} }
} }
@SuppressWarnings("unused")
void handle(String arg) { void handle(String arg) {
} }

Loading…
Cancel
Save