提交 c9f48836 编写于 作者: J Juergen Hoeller

Fine-tuned assertions and related polishing

上级 e17fc8d6
......@@ -265,7 +265,7 @@ class Tokenizer {
raiseParseException(this.pos, SpelMessage.UNEXPECTED_ESCAPE_CHAR);
break;
default:
throw new IllegalStateException("Cannot handle ('" + ch + "')");
throw new IllegalStateException("Cannot handle (" + (int) ch + ") '" + ch + "'");
}
}
}
......
......@@ -414,7 +414,6 @@ public class HttpHeaders implements MultiValueMap<String, String>, Serializable
* Private constructor that can create read-only {@code HttpHeader} instances.
*/
private HttpHeaders(Map<String, List<String>> headers, boolean readOnly) {
Assert.notNull(headers, "'headers' must not be null");
if (readOnly) {
Map<String, List<String>> map = new LinkedCaseInsensitiveMap<>(headers.size(), Locale.ENGLISH);
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.
*/
public static HttpHeaders readOnlyHttpHeaders(HttpHeaders headers) {
Assert.notNull(headers, "HttpHeaders must not be null");
return (headers.readOnly ? headers : new HttpHeaders(headers, true));
}
......
......@@ -114,7 +114,7 @@ public interface ClientRequest {
/**
* Create a builder with the given method and url.
* @param method the HTTP method (GET, POST, etc)
* @param url the URL
* @param url the url (as a URI instance)
* @return the created builder
* @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.
* @param method the HTTP method (GET, POST, etc)
* @param url the URL
* @param url the url (as a URI instance)
* @return the created builder
*/
static Builder create(HttpMethod method, URI url) {
......
......@@ -49,28 +49,30 @@ import org.springframework.web.reactive.function.BodyInserters;
*/
final class DefaultClientRequestBuilder implements ClientRequest.Builder {
private HttpMethod method;
private URI url;
private final HttpHeaders headers = new HttpHeaders();
private final MultiValueMap<String, String> cookies = new LinkedMultiValueMap<>();
private final Map<String, Object> attributes = new LinkedHashMap<>();
private HttpMethod method;
private URI url;
private BodyInserter<?, ? super ClientHttpRequest> inserter = BodyInserters.empty();
private BodyInserter<?, ? super ClientHttpRequest> body = BodyInserters.empty();
public DefaultClientRequestBuilder(HttpMethod method, URI url) {
method(method);
url(url);
Assert.notNull(method, "HttpMethod must not be null");
Assert.notNull(url, "URI must not be null");
this.method = method;
this.url = url;
}
public DefaultClientRequestBuilder(ClientRequest other) {
Assert.notNull(other, "ClientRequest must not be null");
method(other.method());
url(other.url());
this.method = other.method();
this.url = other.url();
headers(headers -> headers.addAll(other.headers()));
cookies(cookies -> cookies.addAll(other.cookies()));
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(elementClass, "'elementClass' must not be null");
this.inserter = BodyInserters.fromPublisher(publisher, elementClass);
this.body = BodyInserters.fromPublisher(publisher, elementClass);
return this;
}
......@@ -136,7 +138,7 @@ final class DefaultClientRequestBuilder implements ClientRequest.Builder {
Assert.notNull(publisher, "'publisher' 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;
}
......@@ -154,14 +156,13 @@ final class DefaultClientRequestBuilder implements ClientRequest.Builder {
@Override
public ClientRequest.Builder body(BodyInserter<?, ? super ClientHttpRequest> inserter) {
this.inserter = inserter;
this.body = inserter;
return this;
}
@Override
public ClientRequest build() {
return new BodyInserterRequest(this.method, this.url, this.headers, this.cookies,
this.inserter, this.attributes);
return new BodyInserterRequest(this.method, this.url, this.headers, this.cookies, this.body, this.attributes);
}
......@@ -175,20 +176,19 @@ final class DefaultClientRequestBuilder implements ClientRequest.Builder {
private final MultiValueMap<String, String> cookies;
private final BodyInserter<?, ? super ClientHttpRequest> inserter;
private final BodyInserter<?, ? super ClientHttpRequest> body;
private final Map<String, Object> attributes;
public BodyInserterRequest(HttpMethod method, URI url, HttpHeaders headers,
MultiValueMap<String, String> cookies,
BodyInserter<?, ? super ClientHttpRequest> inserter,
MultiValueMap<String, String> cookies, BodyInserter<?, ? super ClientHttpRequest> body,
Map<String, Object> attributes) {
this.method = method;
this.url = url;
this.headers = HttpHeaders.readOnlyHttpHeaders(headers);
this.cookies = CollectionUtils.unmodifiableMultiValueMap(cookies);
this.inserter = inserter;
this.body = body;
this.attributes = Collections.unmodifiableMap(attributes);
}
......@@ -214,7 +214,7 @@ final class DefaultClientRequestBuilder implements ClientRequest.Builder {
@Override
public BodyInserter<?, ? super ClientHttpRequest> body() {
return this.inserter;
return this.body;
}
@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
public List<HttpMessageWriter<?>> messageWriters() {
return strategies.messageWriters();
}
@Override
public Optional<ServerHttpRequest> serverRequest() {
return Optional.empty();
}
@Override
public Map<String, Object> hints() {
return Collections.emptyMap();
......
......@@ -42,16 +42,16 @@ import org.springframework.util.MultiValueMap;
*/
final class DefaultClientResponseBuilder implements ClientResponse.Builder {
private ExchangeStrategies strategies;
private HttpStatus statusCode = HttpStatus.OK;
private final HttpHeaders headers = new HttpHeaders();
private final MultiValueMap<String, ResponseCookie> cookies = new LinkedMultiValueMap<>();
private HttpStatus statusCode = HttpStatus.OK;
private Flux<DataBuffer> body = Flux.empty();
private ExchangeStrategies strategies;
public DefaultClientResponseBuilder(ExchangeStrategies strategies) {
Assert.notNull(strategies, "ExchangeStrategies must not be null");
......@@ -84,7 +84,6 @@ final class DefaultClientResponseBuilder implements ClientResponse.Builder {
@Override
public ClientResponse.Builder headers(Consumer<HttpHeaders> headersConsumer) {
Assert.notNull(headersConsumer, "Consumer must not be null");
headersConsumer.accept(this.headers);
return this;
}
......@@ -99,7 +98,6 @@ final class DefaultClientResponseBuilder implements ClientResponse.Builder {
@Override
public ClientResponse.Builder cookies(Consumer<MultiValueMap<String, ResponseCookie>> cookiesConsumer) {
Assert.notNull(cookiesConsumer, "Consumer must not be null");
cookiesConsumer.accept(this.cookies);
return this;
}
......
......@@ -208,9 +208,7 @@ final class DefaultWebClientBuilder implements WebClient.Builder {
private static @Nullable HttpHeaders unmodifiableCopy(@Nullable HttpHeaders original) {
if (original != null) {
HttpHeaders copy = new HttpHeaders();
copy.putAll(original);
return HttpHeaders.readOnlyHttpHeaders(copy);
return HttpHeaders.readOnlyHttpHeaders(original);
}
else {
return null;
......
......@@ -96,7 +96,6 @@ class DefaultEntityResponseBuilder<T> implements EntityResponse.Builder<T> {
@Override
public EntityResponse.Builder<T> cookies(Consumer<MultiValueMap<String, ResponseCookie>> cookiesConsumer) {
Assert.notNull(cookiesConsumer, "Consumer must not be null");
cookiesConsumer.accept(this.cookies);
return this;
}
......
......@@ -99,7 +99,6 @@ final class DefaultRenderingResponseBuilder implements RenderingResponse.Builder
@Override
public RenderingResponse.Builder cookies(Consumer<MultiValueMap<String, ResponseCookie>> cookiesConsumer) {
Assert.notNull(cookiesConsumer, "Consumer must not be null");
cookiesConsumer.accept(this.cookies);
return this;
}
......
......@@ -76,14 +76,10 @@ class DefaultServerRequest implements ServerRequest {
DefaultServerRequest(ServerWebExchange exchange, List<HttpMessageReader<?>> messageReaders) {
this.exchange = exchange;
this.messageReaders = unmodifiableCopy(messageReaders);
this.messageReaders = Collections.unmodifiableList(new ArrayList<>(messageReaders));
this.headers = new DefaultHeaders();
}
private static <T> List<T> unmodifiableCopy(List<? extends T> list) {
return Collections.unmodifiableList(new ArrayList<>(list));
}
@Override
public String methodName() {
......
......@@ -67,37 +67,39 @@ import org.springframework.web.util.UriUtils;
*/
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 ServerWebExchange exchange;
private HttpMethod method = HttpMethod.GET;
private String methodName;
@Nullable
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();
public DefaultServerRequestBuilder(ServerRequest other) {
Assert.notNull(other, "ServerRequest must not be null");
this.messageReaders = other.messageReaders();
this.exchange = other.exchange();
method(other.method());
uri(other.uri());
this.methodName = other.methodName();
this.uri = other.uri();
headers(headers -> headers.addAll(other.headers().asHttpHeaders()));
cookies(cookies -> cookies.addAll(other.cookies()));
attributes(attributes -> attributes.putAll(other.attributes()));
}
@Override
public ServerRequest.Builder method(HttpMethod method) {
Assert.notNull(method, "'method' must not be null");
this.method = method;
this.methodName = method.name();
return this;
}
......@@ -118,7 +120,6 @@ class DefaultServerRequestBuilder implements ServerRequest.Builder {
@Override
public ServerRequest.Builder headers(Consumer<HttpHeaders> headersConsumer) {
Assert.notNull(headersConsumer, "'headersConsumer' must not be null");
headersConsumer.accept(this.headers);
return this;
}
......@@ -132,10 +133,7 @@ class DefaultServerRequestBuilder implements ServerRequest.Builder {
}
@Override
public ServerRequest.Builder cookies(
Consumer<MultiValueMap<String, HttpCookie>> cookiesConsumer) {
Assert.notNull(cookiesConsumer, "'cookiesConsumer' must not be null");
public ServerRequest.Builder cookies(Consumer<MultiValueMap<String, HttpCookie>> cookiesConsumer) {
cookiesConsumer.accept(this.cookies);
return this;
}
......@@ -174,26 +172,25 @@ class DefaultServerRequestBuilder implements ServerRequest.Builder {
@Override
public ServerRequest.Builder attributes(Consumer<Map<String, Object>> attributesConsumer) {
Assert.notNull(attributesConsumer, "'attributesConsumer' must not be null");
attributesConsumer.accept(this.attributes);
return this;
}
@Override
public ServerRequest build() {
ServerHttpRequest serverHttpRequest = new BuiltServerHttpRequest(this.method, this.uri,
this.headers, this.cookies, this.body);
ServerWebExchange exchange = new DelegatingServerWebExchange(serverHttpRequest,
this.exchange, this.messageReaders);
ServerHttpRequest serverHttpRequest = new BuiltServerHttpRequest(
this.methodName, this.uri, this.headers, this.cookies, this.body);
ServerWebExchange exchange = new DelegatingServerWebExchange(
serverHttpRequest, this.exchange, this.messageReaders);
return new DefaultServerRequest(exchange, this.messageReaders);
}
private static class BuiltServerHttpRequest implements ServerHttpRequest {
private static final Pattern QUERY_PATTERN = Pattern.compile("([^&=]+)(=?)([^&]+)?");
private final HttpMethod method;
private final String method;
private final URI uri;
......@@ -207,10 +204,9 @@ class DefaultServerRequestBuilder implements ServerRequest.Builder {
private final Flux<DataBuffer> body;
public BuiltServerHttpRequest(HttpMethod method, URI uri,
HttpHeaders headers,
MultiValueMap<String, HttpCookie> cookies,
Flux<DataBuffer> body) {
public BuiltServerHttpRequest(String method, URI uri, HttpHeaders headers,
MultiValueMap<String, HttpCookie> cookies, Flux<DataBuffer> body) {
this.method = method;
this.uri = uri;
this.path = RequestPath.parse(uri, null);
......@@ -245,15 +241,9 @@ class DefaultServerRequestBuilder implements ServerRequest.Builder {
return queryParams;
}
@Nullable
@Override
public HttpMethod getMethod() {
return this.method;
}
@Override
public String getMethodValue() {
return this.method.name();
return this.method;
}
@Override
......@@ -287,6 +277,7 @@ class DefaultServerRequestBuilder implements ServerRequest.Builder {
}
}
private static class DelegatingServerWebExchange implements ServerWebExchange {
private static final ResolvableType FORM_DATA_TYPE =
......@@ -296,12 +287,10 @@ class DefaultServerRequestBuilder implements ServerRequest.Builder {
MultiValueMap.class, String.class, Part.class);
private static final Mono<MultiValueMap<String, String>> EMPTY_FORM_DATA =
Mono.just(CollectionUtils.unmodifiableMultiValueMap(new LinkedMultiValueMap<String, String>(0)))
.cache();
Mono.just(CollectionUtils.unmodifiableMultiValueMap(new LinkedMultiValueMap<String, String>(0))).cache();
private static final Mono<MultiValueMap<String, Part>> EMPTY_MULTIPART_DATA =
Mono.just(CollectionUtils.unmodifiableMultiValueMap(new LinkedMultiValueMap<String, Part>(0)))
.cache();
Mono.just(CollectionUtils.unmodifiableMultiValueMap(new LinkedMultiValueMap<String, Part>(0))).cache();
private final ServerHttpRequest request;
......@@ -311,8 +300,9 @@ class DefaultServerRequestBuilder implements ServerRequest.Builder {
private final Mono<MultiValueMap<String, Part>> multipartDataMono;
public DelegatingServerWebExchange(ServerHttpRequest request, ServerWebExchange delegate,
List<HttpMessageReader<?>> messageReaders) {
public DelegatingServerWebExchange(
ServerHttpRequest request, ServerWebExchange delegate, List<HttpMessageReader<?>> messageReaders) {
this.request = request;
this.delegate = delegate;
this.formDataMono = initFormData(request, messageReaders);
......@@ -399,7 +389,6 @@ class DefaultServerRequestBuilder implements ServerRequest.Builder {
return this.delegate.getPrincipal();
}
@Override
public LocaleContext getLocaleContext() {
return this.delegate.getLocaleContext();
......
......@@ -97,7 +97,6 @@ class DefaultServerResponseBuilder implements ServerResponse.BodyBuilder {
@Override
public ServerResponse.BodyBuilder headers(Consumer<HttpHeaders> headersConsumer) {
Assert.notNull(headersConsumer, "Consumer must not be null");
headersConsumer.accept(this.headers);
return this;
}
......@@ -111,7 +110,6 @@ class DefaultServerResponseBuilder implements ServerResponse.BodyBuilder {
@Override
public ServerResponse.BodyBuilder cookies(Consumer<MultiValueMap<String, ResponseCookie>> cookiesConsumer) {
Assert.notNull(cookiesConsumer, "Consumer must not be null");
cookiesConsumer.accept(this.cookies);
return this;
}
......@@ -201,9 +199,8 @@ class DefaultServerResponseBuilder implements ServerResponse.BodyBuilder {
public Mono<ServerResponse> build(
BiFunction<ServerWebExchange, ServerResponse.Context, Mono<Void>> writeFunction) {
Assert.notNull(writeFunction, "BiFunction must not be null");
return Mono.just(
new WriterFunctionServerResponse(this.statusCode, this.headers, this.cookies, writeFunction));
new WriterFunctionResponse(this.statusCode, this.headers, this.cookies, writeFunction));
}
@Override
......@@ -250,15 +247,12 @@ class DefaultServerResponseBuilder implements ServerResponse.BodyBuilder {
@Override
public Mono<ServerResponse> body(BodyInserter<?, ? super ServerHttpResponse> inserter) {
Assert.notNull(inserter, "BodyInserter must not be null");
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
public Mono<ServerResponse> render(String name, Object... modelAttributes) {
Assert.hasLength(name, "Name must not be empty");
return new DefaultRenderingResponseBuilder(name)
.headers(this.headers)
.status(this.statusCode)
......@@ -269,8 +263,6 @@ class DefaultServerResponseBuilder implements ServerResponse.BodyBuilder {
@Override
public Mono<ServerResponse> render(String name, Map<String, ?> model) {
Assert.hasLength(name, "Name must not be empty");
return new DefaultRenderingResponseBuilder(name)
.headers(this.headers)
.status(this.statusCode)
......@@ -290,24 +282,12 @@ class DefaultServerResponseBuilder implements ServerResponse.BodyBuilder {
private final MultiValueMap<String, ResponseCookie> cookies;
protected AbstractServerResponse(int statusCode, HttpHeaders headers,
MultiValueMap<String, ResponseCookie> cookies) {
protected AbstractServerResponse(
int statusCode, HttpHeaders headers, MultiValueMap<String, ResponseCookie> cookies) {
this.statusCode = statusCode;
this.headers = readOnlyCopy(headers);
this.cookies = readOnlyCopy(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);
this.headers = HttpHeaders.readOnlyHttpHeaders(headers);
this.cookies = CollectionUtils.unmodifiableMultiValueMap(new LinkedMultiValueMap<>(cookies));
}
@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;
public WriterFunctionServerResponse(int statusCode, HttpHeaders headers,
public WriterFunctionResponse(int statusCode, HttpHeaders headers,
MultiValueMap<String, ResponseCookie> cookies,
BiFunction<ServerWebExchange, Context, Mono<Void>> writeFunction) {
super(statusCode, headers, cookies);
Assert.notNull(writeFunction, "BiFunction must not be null");
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 Map<String, Object> hints;
public BodyInserterServerResponse(int statusCode, HttpHeaders headers,
public BodyInserterResponse(int statusCode, HttpHeaders headers,
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);
this.inserter = inserter;
Assert.notNull(body, "BodyInserter must not be null");
this.inserter = body;
this.hints = hints;
}
......
......@@ -43,7 +43,6 @@ import org.springframework.http.codec.multipart.Part;
import org.springframework.http.server.PathContainer;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
import org.springframework.util.CollectionUtils;
import org.springframework.util.MultiValueMap;
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.
* @since 5.1
*/
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
* {@code "application/x-www-form-urlencoded"} or an empty map otherwise.
*
* <p><strong>Note:</strong> calling this method causes the request body to
* be read and parsed in full and the resulting {@code MultiValueMap} is
* 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
* {@code "multipart/form-data"} or an empty map otherwise.
*
* <p><strong>Note:</strong> calling this method causes the request body to
* be read and parsed in full and the resulting {@code MultiValueMap} is
* cached so that this method is safe to call more than once.
......@@ -280,14 +278,14 @@ public interface ServerRequest {
Mono<MultiValueMap<String, Part>> multipartData();
/**
* Returns the web exchange that this request is based on. Manipulating the exchange directly,
* instead of using the methods provided on {@code ServerRequest} and {@code ServerResponse},
* can lead to irregular results.
*
* @return the web exchange
* Return the web exchange that this request is based on.
* <p>Note: Manipulating the exchange directly (instead of using the methods provided on
* {@code ServerRequest} and {@code ServerResponse}) can lead to irregular results.
* @since 5.1
*/
ServerWebExchange exchange();
// Static methods
/**
......@@ -305,12 +303,13 @@ public interface ServerRequest {
* 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
* @return the created builder
* @since 5.1
*/
static Builder from(ServerRequest other) {
Assert.notNull(other, "'other' must not be null");
return new DefaultServerRequestBuilder(other);
}
/**
* Represents the headers of the HTTP request.
* @see ServerRequest#headers()
......@@ -378,6 +377,7 @@ public interface ServerRequest {
/**
* Defines a builder for a request.
* @since 5.1
*/
interface Builder {
......
......@@ -328,6 +328,8 @@ public class ResponseEntityExceptionHandlerTests {
}
}
@SuppressWarnings("unused")
void handle(String arg) {
}
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册