Remove ServerWebExchange#getRequestParams

Issue: SPR-15508
This commit is contained in:
Rossen Stoyanchev 2017-05-02 16:08:50 -04:00
parent 7f19e57d9d
commit 1881727b37
16 changed files with 115 additions and 314 deletions

View File

@ -16,7 +16,6 @@
package org.springframework.web.bind.support;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;
@ -24,10 +23,10 @@ import java.util.TreeMap;
import reactor.core.publisher.Mono;
import org.springframework.beans.MutablePropertyValues;
import org.springframework.http.codec.multipart.Part;
import org.springframework.util.CollectionUtils;
import org.springframework.util.MultiValueMap;
import org.springframework.web.bind.WebDataBinder;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.server.ServerWebExchange;
/**
@ -39,6 +38,7 @@ import org.springframework.web.server.ServerWebExchange;
*/
public class WebExchangeDataBinder extends WebDataBinder {
/**
* Create a new instance, with default object name.
* @param target the target object to bind onto (or {@code null} if the
@ -61,62 +61,52 @@ public class WebExchangeDataBinder extends WebDataBinder {
/**
* Bind the URL query parameters or form data of the body of the given request
* to this binder's target. The request body is parsed if the Content-Type
* is {@code "application/x-www-form-urlencoded"}.
* Bind query params, form data, and or multipart form data to the binder target.
* @param exchange the current exchange.
* @return a {@code Mono<Void>} when binding is complete
*/
public Mono<Void> bind(ServerWebExchange exchange) {
return exchange.getRequestParams()
.map(this::getParamsToBind)
.doOnNext(values -> values.putAll(getMultipartFiles(exchange)))
.doOnNext(values -> values.putAll(getExtraValuesToBind(exchange)))
.flatMap(values -> {
doBind(new MutablePropertyValues(values));
return Mono.empty();
return getValuesToBind(exchange)
.doOnNext(values -> doBind(new MutablePropertyValues(values)))
.then();
}
/**
* Protected method to obtain the values for data binding. By default this
* method delegates to {@link #extractValuesToBind(ServerWebExchange)}.
*/
protected Mono<Map<String, Object>> getValuesToBind(ServerWebExchange exchange) {
return extractValuesToBind(exchange);
}
/**
* Combine query params and form data for multipart form data from the body
* of the request into a {@code Map<String, Object>} of values to use for
* data binding purposes.
*
* @param exchange the current exchange
* @return a {@code Mono} with the values to bind
*/
public static Mono<Map<String, Object>> extractValuesToBind(ServerWebExchange exchange) {
MultiValueMap<String, String> queryParams = exchange.getRequest().getQueryParams();
Mono<MultiValueMap<String, String>> formData = exchange.getFormData();
Mono<MultiValueMap<String, Part>> multipartData = exchange.getMultipartData();
return Mono.when(Mono.just(queryParams), formData, multipartData)
.map(tuple -> {
Map<String, Object> result = new TreeMap<>();
tuple.getT1().forEach((key, values) -> addBindValue(result, key, values));
tuple.getT2().forEach((key, values) -> addBindValue(result, key, values));
tuple.getT3().forEach((key, values) -> addBindValue(result, key, values));
return result;
});
}
private Map<String, Object> getParamsToBind(MultiValueMap<String, String> params) {
Map<String, Object> result = new TreeMap<>();
for (Map.Entry<String, List<String>> entry : params.entrySet()) {
String name = entry.getKey();
List<String> values = entry.getValue();
if (CollectionUtils.isEmpty(values)) {
// Do nothing, no values found at all.
}
else if (values.size() == 1) {
result.put(name, values.get(0));
}
else {
result.put(name, values);
}
private static void addBindValue(Map<String, Object> params, String key, List<?> values) {
if (!CollectionUtils.isEmpty(values)) {
params.put(key, values.size() == 1 ? values.get(0) : values);
}
return result;
}
/**
* Bind all multipart files contained in the given request, if any (in case
* of a multipart request).
* <p>Multipart files will only be added to the property values if they
* are not empty or if we're configured to bind empty multipart files too.
* @param exchange the current exchange
* @return Map of field name String to MultipartFile object
*/
protected Map<String, List<MultipartFile>> getMultipartFiles(ServerWebExchange exchange) {
// TODO
return Collections.emptyMap();
}
/**
* Extension point that subclasses can use to add extra bind values for a
* request. Invoked before {@link #doBind(MutablePropertyValues)}.
* <p>The default implementation is empty.
* @param exchange the current exchange
*/
protected Map<String, ?> getExtraValuesToBind(ServerWebExchange exchange) {
return Collections.emptyMap();
}
}

View File

@ -1,5 +1,5 @@
/*
* Copyright 2002-2015 the original author or authors.
* Copyright 2002-2017 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.
@ -80,24 +80,23 @@ public interface ServerWebExchange {
/**
* 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.
* This method may be called multiple times.
*
* <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.
*/
Mono<MultiValueMap<String, String>> getFormData();
/**
* Return the parts of a multipart request if the Content-Type is
* {@code "multipart/form-data"} or an empty map otherwise.
* This method may be called multiple times.
*
* <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.
*/
Mono<MultiValueMap<String, Part>> getMultipartData();
/**
* Return a combined map that represents both
* {@link ServerHttpRequest#getQueryParams()} and {@link #getFormData()}
* or an empty map.
*/
Mono<MultiValueMap<String, String>> getRequestParams();
/**
* Returns {@code true} if the one of the {@code checkNotModified} methods
* in this contract were used and they returned true.

View File

@ -99,11 +99,6 @@ public class ServerWebExchangeDecorator implements ServerWebExchange {
return getDelegate().getMultipartData();
}
@Override
public Mono<MultiValueMap<String, String>> getRequestParams() {
return getDelegate().getRequestParams();
}
@Override
public boolean isNotModified() {
return getDelegate().isNotModified();

View File

@ -1,5 +1,5 @@
/*
* Copyright 2002-2016 the original author or authors.
* Copyright 2002-2017 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.
@ -88,8 +88,6 @@ public class DefaultServerWebExchange implements ServerWebExchange {
private final Mono<MultiValueMap<String, Part>> multipartDataMono;
private final Mono<MultiValueMap<String, String>> requestParamsMono;
private volatile boolean notModified;
@ -109,8 +107,6 @@ public class DefaultServerWebExchange implements ServerWebExchange {
this.sessionMono = sessionManager.getSession(this).cache();
this.formDataMono = initFormData(request, codecConfigurer);
this.multipartDataMono = initMultipartData(request, codecConfigurer);
this.requestParamsMono = initRequestParams(request, this.formDataMono);
}
@SuppressWarnings("unchecked")
@ -165,20 +161,6 @@ public class DefaultServerWebExchange implements ServerWebExchange {
return EMPTY_MULTIPART_DATA;
}
private static Mono<MultiValueMap<String, String>> initRequestParams(
ServerHttpRequest request, Mono<MultiValueMap<String, String>> formDataMono) {
return formDataMono
.map(formData -> {
MultiValueMap<String, String> result = new LinkedMultiValueMap<>();
result.putAll(request.getQueryParams());
result.putAll(formData);
return CollectionUtils.unmodifiableMultiValueMap(result);
})
.defaultIfEmpty(request.getQueryParams())
.cache();
}
@Override
public ServerHttpRequest getRequest() {
@ -228,11 +210,6 @@ public class DefaultServerWebExchange implements ServerWebExchange {
return this.multipartDataMono;
}
@Override
public Mono<MultiValueMap<String, String>> getRequestParams() {
return this.requestParamsMono;
}
@Override
public boolean isNotModified() {
return this.notModified;

View File

@ -21,8 +21,6 @@ import java.util.Collections;
import java.util.LinkedHashSet;
import java.util.Set;
import org.springframework.util.Assert;
import org.springframework.util.MultiValueMap;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.server.ServerWebExchange;
@ -143,18 +141,12 @@ public final class ParamsRequestCondition extends AbstractRequestCondition<Param
@Override
protected boolean matchName(ServerWebExchange exchange) {
return getRequestParams(exchange).containsKey(this.name);
return exchange.getRequest().getQueryParams().containsKey(this.name);
}
@Override
protected boolean matchValue(ServerWebExchange exchange) {
return this.value.equals(getRequestParams(exchange).getFirst(this.name));
}
private MultiValueMap<String, String> getRequestParams(ServerWebExchange exchange) {
MultiValueMap<String, String> params = exchange.getRequestParams().subscribe().peek();
Assert.notNull(params, "Expected form data (if any) to be parsed.");
return params;
return this.value.equals(exchange.getRequest().getQueryParams().getFirst(this.name));
}
}

View File

@ -258,32 +258,26 @@ public abstract class AbstractHandlerMethodMapping<T> extends AbstractHandlerMap
logger.debug("Looking up handler method for path " + lookupPath);
}
this.mappingRegistry.acquireReadLock();
try {
// Ensure form data is parsed for "params" conditions...
return exchange.getRequestParams()
.then(exchange.getMultipartData())
.then(Mono.defer(() -> {
HandlerMethod handlerMethod = null;
try {
handlerMethod = lookupHandlerMethod(lookupPath, exchange);
}
catch (Exception ex) {
return Mono.error(ex);
}
if (logger.isDebugEnabled()) {
if (handlerMethod != null) {
logger.debug("Returning handler method [" + handlerMethod + "]");
}
else {
logger.debug("Did not find handler method for [" + lookupPath + "]");
}
}
if (handlerMethod != null) {
handlerMethod = handlerMethod.createWithResolvedBean();
}
return Mono.justOrEmpty(handlerMethod);
}));
HandlerMethod handlerMethod;
try {
handlerMethod = lookupHandlerMethod(lookupPath, exchange);
}
catch (Exception ex) {
return Mono.error(ex);
}
if (logger.isDebugEnabled()) {
if (handlerMethod != null) {
logger.debug("Returning handler method [" + handlerMethod + "]");
}
else {
logger.debug("Did not find handler method for [" + lookupPath + "]");
}
}
if (handlerMethod != null) {
handlerMethod = handlerMethod.createWithResolvedBean();
}
return Mono.justOrEmpty(handlerMethod);
}
finally {
this.mappingRegistry.releaseReadLock();

View File

@ -133,8 +133,8 @@ class ControllerMethodResolver {
// Annotation-based...
registrar.add(new RequestParamMethodArgumentResolver(beanFactory, reactiveRegistry, false));
registrar.add(new RequestPartMethodArgumentResolver(beanFactory, reactiveRegistry, false));
registrar.add(new RequestParamMapMethodArgumentResolver(reactiveRegistry));
registrar.add(new RequestPartMethodArgumentResolver(reactiveRegistry));
registrar.add(new PathVariableMethodArgumentResolver(beanFactory, reactiveRegistry));
registrar.add(new PathVariableMapMethodArgumentResolver(reactiveRegistry));
registrar.addIfRequestBody(readers -> new RequestBodyArgumentResolver(readers, reactiveRegistry));

View File

@ -216,7 +216,7 @@ public class ModelAttributeMethodArgumentResolver extends HandlerMethodArgumentR
}
// A single data class constructor -> resolve constructor arguments from request parameters.
return exchange.getRequestParams().map(requestParams -> {
return WebExchangeDataBinder.extractValuesToBind(exchange).map(bindValues -> {
ConstructorProperties cp = ctor.getAnnotation(ConstructorProperties.class);
String[] paramNames = (cp != null ? cp.value() : parameterNameDiscoverer.getParameterNames(ctor));
Assert.state(paramNames != null, () -> "Cannot resolve parameter names for constructor " + ctor);
@ -226,13 +226,9 @@ public class ModelAttributeMethodArgumentResolver extends HandlerMethodArgumentR
Object[] args = new Object[paramTypes.length];
WebDataBinder binder = context.createDataBinder(exchange, null, attributeName);
for (int i = 0; i < paramNames.length; i++) {
List<String> paramValues = requestParams.get(paramNames[i]);
Object paramValue = null;
if (paramValues != null) {
paramValue = (paramValues.size() == 1 ? paramValues.get(0) :
paramValues.toArray(new String[paramValues.size()]));
}
args[i] = binder.convertIfNecessary(paramValue, paramTypes[i], new MethodParameter(ctor, i));
Object value = bindValues.get(paramNames[i]);
value = (value != null && value instanceof List ? ((List<?>) value).toArray() : value);
args[i] = binder.convertIfNecessary(value, paramTypes[i], new MethodParameter(ctor, i));
}
return BeanUtils.instantiateClass(ctor, args);
});

View File

@ -21,9 +21,6 @@ import java.util.Optional;
import org.springframework.core.MethodParameter;
import org.springframework.core.ReactiveAdapterRegistry;
import org.springframework.core.ResolvableType;
import org.springframework.http.codec.multipart.Part;
import org.springframework.util.Assert;
import org.springframework.util.MultiValueMap;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.RequestParam;
@ -51,6 +48,7 @@ import org.springframework.web.server.ServerWebExchange;
public class RequestParamMapMethodArgumentResolver extends HandlerMethodArgumentResolverSupport
implements SyncHandlerMethodArgumentResolver {
public RequestParamMapMethodArgumentResolver(ReactiveAdapterRegistry adapterRegistry) {
super(adapterRegistry);
}
@ -70,18 +68,10 @@ public class RequestParamMapMethodArgumentResolver extends HandlerMethodArgument
public Optional<Object> resolveArgumentValue(MethodParameter methodParameter,
BindingContext context, ServerWebExchange exchange) {
ResolvableType paramType = ResolvableType.forType(methodParameter.getGenericParameterType());
boolean isMultiValueMap = MultiValueMap.class.isAssignableFrom(paramType.getRawClass());
if (paramType.getGeneric(1).getRawClass() == Part.class) {
MultiValueMap<String, Part> requestParts = exchange.getMultipartData().subscribe().peek();
Assert.notNull(requestParts, "Expected multipart data (if any) to be parsed.");
return Optional.of(isMultiValueMap ? requestParts : requestParts.toSingleValueMap());
}
MultiValueMap<String, String> requestParams = exchange.getRequestParams().subscribe().peek();
Assert.notNull(requestParams, "Expected form data (if any) to be parsed.");
return Optional.of(isMultiValueMap ? requestParams : requestParams.toSingleValueMap());
boolean isMultiValueMap = MultiValueMap.class.isAssignableFrom(methodParameter.getParameterType());
MultiValueMap<String, String> queryParams = exchange.getRequest().getQueryParams();
Object value = isMultiValueMap ? queryParams : queryParams.toSingleValueMap();
return Optional.of(value);
}
}

View File

@ -25,9 +25,6 @@ import org.springframework.beans.factory.config.ConfigurableBeanFactory;
import org.springframework.core.MethodParameter;
import org.springframework.core.ReactiveAdapterRegistry;
import org.springframework.core.convert.converter.Converter;
import org.springframework.http.codec.multipart.Part;
import org.springframework.util.Assert;
import org.springframework.util.MultiValueMap;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ValueConstants;
@ -35,7 +32,8 @@ import org.springframework.web.server.ServerWebExchange;
import org.springframework.web.server.ServerWebInputException;
/**
* Resolver for method arguments annotated with @{@link RequestParam}.
* Resolver for method arguments annotated with @{@link RequestParam} from URI
* query string parameters.
*
* <p>This resolver can also be created in default resolution mode in which
* simple types (int, long, etc.) not annotated with @{@link RequestParam} are
@ -103,7 +101,7 @@ public class RequestParamMethodArgumentResolver extends AbstractNamedValueSyncAr
protected Optional<Object> resolveNamedValue(String name, MethodParameter parameter,
ServerWebExchange exchange) {
List<?> paramValues = parameter.getParameter().getType() == Part.class ? getMultipartData(exchange).get(name) : getRequestParams(exchange).get(name);
List<String> paramValues = exchange.getRequest().getQueryParams().get(name);
Object result = null;
if (paramValues != null) {
result = (paramValues.size() == 1 ? paramValues.get(0) : paramValues);
@ -111,18 +109,6 @@ public class RequestParamMethodArgumentResolver extends AbstractNamedValueSyncAr
return Optional.ofNullable(result);
}
private MultiValueMap<String, String> getRequestParams(ServerWebExchange exchange) {
MultiValueMap<String, String> params = exchange.getRequestParams().subscribe().peek();
Assert.notNull(params, "Expected form data (if any) to be parsed.");
return params;
}
private MultiValueMap<String, Part> getMultipartData(ServerWebExchange exchange) {
MultiValueMap<String, Part> params = exchange.getMultipartData().subscribe().peek();
Assert.notNull(params, "Expected multipart data (if any) to be parsed.");
return params;
}
@Override
protected void handleMissingValue(String name, MethodParameter parameter, ServerWebExchange exchange) {
String type = parameter.getNestedParameterType().getSimpleName();

View File

@ -17,19 +17,13 @@
package org.springframework.web.reactive.result.method.annotation;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
import reactor.core.publisher.Mono;
import org.springframework.core.MethodParameter;
import org.springframework.core.ReactiveAdapterRegistry;
import org.springframework.core.convert.converter.Converter;
import org.springframework.http.codec.multipart.Part;
import org.springframework.util.Assert;
import org.springframework.util.MultiValueMap;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.util.CollectionUtils;
import org.springframework.web.bind.annotation.RequestPart;
import org.springframework.web.bind.annotation.ValueConstants;
import org.springframework.web.server.ServerWebExchange;
@ -39,48 +33,25 @@ import org.springframework.web.server.ServerWebInputException;
* Resolver for method arguments annotated with @{@link RequestPart}.
*
* @author Sebastien Deleuze
* @author Rossen Stoyanchev
* @since 5.0
* @see RequestParamMapMethodArgumentResolver
*/
public class RequestPartMethodArgumentResolver extends AbstractNamedValueSyncArgumentResolver {
private final boolean useDefaultResolution;
public class RequestPartMethodArgumentResolver extends AbstractNamedValueArgumentResolver {
/**
* Class constructor with a default resolution mode flag.
* @param factory a bean factory used for resolving ${...} placeholder
* and #{...} SpEL expressions in default values, or {@code null} if default
* values are not expected to contain expressions
* @param registry for checking reactive type wrappers
* @param useDefaultResolution in default resolution mode a method argument
* that is a simple type, as defined in {@link BeanUtils#isSimpleProperty},
* is treated as a request parameter even if it isn't annotated, the
* request parameter name is derived from the method parameter name.
*/
public RequestPartMethodArgumentResolver(
ConfigurableBeanFactory factory, ReactiveAdapterRegistry registry, boolean useDefaultResolution) {
super(factory, registry);
this.useDefaultResolution = useDefaultResolution;
public RequestPartMethodArgumentResolver(ReactiveAdapterRegistry registry) {
super(null, registry);
}
@Override
public boolean supportsParameter(MethodParameter param) {
if (checkAnnotatedParamNoReactiveWrapper(param, RequestPart.class, this::singleParam)) {
return true;
}
else if (this.useDefaultResolution) {
return checkParameterTypeNoReactiveWrapper(param, BeanUtils::isSimpleProperty) ||
BeanUtils.isSimpleProperty(param.nestedIfOptional().getNestedParameterType());
}
return false;
public boolean supportsParameter(MethodParameter parameter) {
return parameter.hasParameterAnnotation(RequestPart.class);
}
private boolean singleParam(RequestPart requestParam, Class<?> type) {
return !Map.class.isAssignableFrom(type) || StringUtils.hasText(requestParam.name());
}
@Override
protected NamedValueInfo createNamedValueInfo(MethodParameter parameter) {
@ -89,28 +60,21 @@ public class RequestPartMethodArgumentResolver extends AbstractNamedValueSyncArg
}
@Override
protected Optional<Object> resolveNamedValue(String name, MethodParameter parameter,
ServerWebExchange exchange) {
List<?> paramValues = getMultipartData(exchange).get(name);
Object result = null;
if (paramValues != null) {
result = (paramValues.size() == 1 ? paramValues.get(0) : paramValues);
}
return Optional.ofNullable(result);
}
private MultiValueMap<String, Part> getMultipartData(ServerWebExchange exchange) {
MultiValueMap<String, Part> params = exchange.getMultipartData().subscribe().peek();
Assert.notNull(params, "Expected multipart data (if any) to be parsed.");
return params;
protected Mono<Object> resolveName(String name, MethodParameter param, ServerWebExchange exchange) {
return exchange.getMultipartData().flatMap(allParts -> {
List<Part> parts = allParts.get(name);
if (CollectionUtils.isEmpty(parts)) {
return Mono.empty();
}
return Mono.just(parts.size() == 1 ? parts.get(0) : parts);
});
}
@Override
protected void handleMissingValue(String name, MethodParameter parameter, ServerWebExchange exchange) {
String type = parameter.getNestedParameterType().getSimpleName();
protected void handleMissingValue(String name, MethodParameter param, ServerWebExchange exchange) {
String type = param.getNestedParameterType().getSimpleName();
String reason = "Required " + type + " parameter '" + name + "' is not present";
throw new ServerWebInputException(reason, parameter);
throw new ServerWebInputException(reason, param);
}

View File

@ -1,5 +1,5 @@
/*
* Copyright 2002-2012 the original author or authors.
* Copyright 2002-2017 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.
@ -20,8 +20,6 @@ import java.util.Collection;
import org.junit.Test;
import org.springframework.http.MediaType;
import org.springframework.mock.http.server.reactive.test.MockServerHttpRequest;
import org.springframework.mock.http.server.reactive.test.MockServerWebExchange;
import org.springframework.web.server.ServerWebExchange;
@ -50,17 +48,13 @@ public class ParamsRequestConditionTests {
@Test
public void paramPresent() throws Exception {
ParamsRequestCondition condition = new ParamsRequestCondition("foo");
assertNotNull(condition.getMatchingCondition(get("/path?foo=").toExchange()));
assertNotNull(condition.getMatchingCondition(postForm("foo=")));
}
@Test
public void paramPresentNoMatch() throws Exception {
ParamsRequestCondition condition = new ParamsRequestCondition("foo");
assertNull(condition.getMatchingCondition(get("/path?bar=").toExchange()));
assertNull(condition.getMatchingCondition(postForm("bar=")));
}
@Test
@ -72,17 +66,13 @@ public class ParamsRequestConditionTests {
@Test
public void paramValueMatch() throws Exception {
ParamsRequestCondition condition = new ParamsRequestCondition("foo=bar");
assertNotNull(condition.getMatchingCondition(get("/path?foo=bar").toExchange()));
assertNotNull(condition.getMatchingCondition(postForm("foo=bar")));
}
@Test
public void paramValueNoMatch() throws Exception {
ParamsRequestCondition condition = new ParamsRequestCondition("foo=bar");
assertNull(condition.getMatchingCondition(get("/path?foo=bazz").toExchange()));
assertNull(condition.getMatchingCondition(postForm("foo=bazz")));
}
@Test
@ -109,12 +99,4 @@ public class ParamsRequestConditionTests {
assertEquals(2, conditions.size());
}
private static MockServerWebExchange postForm(String formData) {
return MockServerHttpRequest.post("/")
.contentType(MediaType.APPLICATION_FORM_URLENCODED)
.body(formData)
.toExchange();
}
}

View File

@ -91,8 +91,8 @@ public class ControllerMethodResolverTests {
AtomicInteger index = new AtomicInteger(-1);
assertEquals(RequestParamMethodArgumentResolver.class, next(resolvers, index).getClass());
assertEquals(RequestPartMethodArgumentResolver.class, next(resolvers, index).getClass());
assertEquals(RequestParamMapMethodArgumentResolver.class, next(resolvers, index).getClass());
assertEquals(RequestPartMethodArgumentResolver.class, next(resolvers, index).getClass());
assertEquals(PathVariableMethodArgumentResolver.class, next(resolvers, index).getClass());
assertEquals(PathVariableMapMethodArgumentResolver.class, next(resolvers, index).getClass());
assertEquals(RequestBodyArgumentResolver.class, next(resolvers, index).getClass());
@ -130,8 +130,8 @@ public class ControllerMethodResolverTests {
AtomicInteger index = new AtomicInteger(-1);
assertEquals(RequestParamMethodArgumentResolver.class, next(resolvers, index).getClass());
assertEquals(RequestPartMethodArgumentResolver.class, next(resolvers, index).getClass());
assertEquals(RequestParamMapMethodArgumentResolver.class, next(resolvers, index).getClass());
assertEquals(RequestPartMethodArgumentResolver.class, next(resolvers, index).getClass());
assertEquals(PathVariableMethodArgumentResolver.class, next(resolvers, index).getClass());
assertEquals(PathVariableMapMethodArgumentResolver.class, next(resolvers, index).getClass());
assertEquals(ModelAttributeMethodArgumentResolver.class, next(resolvers, index).getClass());
@ -167,7 +167,6 @@ public class ControllerMethodResolverTests {
AtomicInteger index = new AtomicInteger(-1);
assertEquals(RequestParamMethodArgumentResolver.class, next(resolvers, index).getClass());
assertEquals(RequestPartMethodArgumentResolver.class, next(resolvers, index).getClass());
assertEquals(RequestParamMapMethodArgumentResolver.class, next(resolvers, index).getClass());
assertEquals(PathVariableMethodArgumentResolver.class, next(resolvers, index).getClass());
assertEquals(PathVariableMapMethodArgumentResolver.class, next(resolvers, index).getClass());
@ -198,8 +197,8 @@ public class ControllerMethodResolverTests {
AtomicInteger index = new AtomicInteger(-1);
assertEquals(RequestParamMethodArgumentResolver.class, next(resolvers, index).getClass());
assertEquals(RequestPartMethodArgumentResolver.class, next(resolvers, index).getClass());
assertEquals(RequestParamMapMethodArgumentResolver.class, next(resolvers, index).getClass());
assertEquals(RequestPartMethodArgumentResolver.class, next(resolvers, index).getClass());
assertEquals(PathVariableMethodArgumentResolver.class, next(resolvers, index).getClass());
assertEquals(PathVariableMapMethodArgumentResolver.class, next(resolvers, index).getClass());
assertEquals(RequestHeaderMethodArgumentResolver.class, next(resolvers, index).getClass());

View File

@ -16,8 +16,6 @@
package org.springframework.web.reactive.result.method.annotation;
import java.util.Map;
import org.junit.Before;
import org.junit.Test;
import reactor.core.publisher.Mono;
@ -37,7 +35,6 @@ import org.springframework.http.server.reactive.HttpHandler;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RequestPart;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.reactive.DispatcherHandler;
@ -51,10 +48,9 @@ import static org.junit.Assert.assertEquals;
public class MultipartIntegrationTests extends AbstractHttpHandlerIntegrationTests {
private AnnotationConfigApplicationContext wac;
private WebClient webClient;
@Override
@Before
public void setup() throws Exception {
@ -65,26 +61,10 @@ public class MultipartIntegrationTests extends AbstractHttpHandlerIntegrationTes
@Override
protected HttpHandler createHttpHandler() {
this.wac = new AnnotationConfigApplicationContext();
this.wac.register(TestConfiguration.class);
this.wac.refresh();
return WebHttpHandlerBuilder.webHandler(new DispatcherHandler(this.wac)).build();
}
@Test
public void map() {
test("/map");
}
@Test
public void multiValueMap() {
test("/multivaluemap");
}
@Test
public void partParam() {
test("/partparam");
AnnotationConfigApplicationContext wac = new AnnotationConfigApplicationContext();
wac.register(TestConfiguration.class);
wac.refresh();
return WebHttpHandlerBuilder.webHandler(new DispatcherHandler(wac)).build();
}
@Test
@ -122,26 +102,6 @@ public class MultipartIntegrationTests extends AbstractHttpHandlerIntegrationTes
@SuppressWarnings("unused")
static class MultipartController {
@PostMapping("/map")
void map(@RequestParam Map<String, Part> parts) {
assertEquals(2, parts.size());
assertEquals("foo.txt", parts.get("fooPart").getFilename().get());
assertEquals("bar", parts.get("barPart").getContentAsString().block());
}
@PostMapping("/multivaluemap")
void multiValueMap(@RequestParam MultiValueMap<String, Part> parts) {
Map<String, Part> map = parts.toSingleValueMap();
assertEquals(2, map.size());
assertEquals("foo.txt", map.get("fooPart").getFilename().get());
assertEquals("bar", map.get("barPart").getContentAsString().block());
}
@PostMapping("/partparam")
void partParam(@RequestParam Part fooPart) {
assertEquals("foo.txt", fooPart.getFilename().get());
}
@PostMapping("/part")
void part(@RequestPart Part fooPart) {
assertEquals("foo.txt", fooPart.getFilename().get());

View File

@ -36,8 +36,6 @@ import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import static org.springframework.http.MediaType.APPLICATION_FORM_URLENCODED;
import static org.springframework.mock.http.server.reactive.test.MockServerHttpRequest.post;
import static org.springframework.web.method.MvcAnnotationPredicates.requestParam;
/**
@ -46,7 +44,8 @@ import static org.springframework.web.method.MvcAnnotationPredicates.requestPara
*/
public class RequestParamMapMethodArgumentResolverTests {
private RequestParamMapMethodArgumentResolver resolver = new RequestParamMapMethodArgumentResolver(new ReactiveAdapterRegistry());
private final RequestParamMapMethodArgumentResolver resolver =
new RequestParamMapMethodArgumentResolver(new ReactiveAdapterRegistry());
private ResolvableMethod testMethod = ResolvableMethod.on(getClass()).named("handle").build();
@ -85,15 +84,6 @@ public class RequestParamMapMethodArgumentResolverTests {
assertEquals(Collections.singletonMap("foo", "bar"), result);
}
@Test
public void resolveMapArgumentWithFormData() throws Exception {
MethodParameter param = this.testMethod.annot(requestParam().name("")).arg(Map.class);
ServerWebExchange exchange = post("/").contentType(APPLICATION_FORM_URLENCODED).body("foo=bar").toExchange();
Object result= resolve(param, exchange);
assertTrue(result instanceof Map);
assertEquals(Collections.singletonMap("foo", "bar"), result);
}
@Test
public void resolveMultiValueMapArgument() throws Exception {
MethodParameter param = this.testMethod.annotPresent(RequestParam.class).arg(MultiValueMap.class);

View File

@ -28,7 +28,6 @@ import reactor.test.StepVerifier;
import org.springframework.core.MethodParameter;
import org.springframework.core.ReactiveAdapterRegistry;
import org.springframework.format.support.DefaultFormattingConversionService;
import org.springframework.http.MediaType;
import org.springframework.mock.http.server.reactive.test.MockServerHttpRequest;
import org.springframework.mock.http.server.reactive.test.MockServerWebExchange;
import org.springframework.web.bind.annotation.RequestParam;
@ -139,18 +138,6 @@ public class RequestParamMethodArgumentResolverTests {
assertEquals("foo", resolve(param, MockServerHttpRequest.get("/path?name=foo").toExchange()));
}
@Test
public void resolveWithFormData() throws Exception {
ServerWebExchange exchange = MockServerHttpRequest.post("/path")
.contentType(MediaType.APPLICATION_FORM_URLENCODED)
.body("name=foo")
.toExchange();
MethodParameter param = this.testMethod.annot(requestParam().notRequired("bar")).arg(String.class);
assertEquals("foo", resolve(param, exchange));
}
@Test
public void resolveStringArray() throws Exception {
MethodParameter param = this.testMethod.annotPresent(RequestParam.class).arg(String[].class);