Consistent java.util.Optional resolution, lenient handling of optional multipart files, correct Servlet 3.0 Part list/array selection
Issue: SPR-13418 Issue: SPR-13849 Issue: SPR-13850 Issue: SPR-13893
This commit is contained in:
parent
a3a5a03ee3
commit
b4f33adf48
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2002-2015 the original author or authors.
|
||||
* Copyright 2002-2016 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.
|
||||
|
|
@ -27,17 +27,16 @@ import java.util.HashMap;
|
|||
import java.util.Map;
|
||||
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.ClassUtils;
|
||||
|
||||
/**
|
||||
* Helper class that encapsulates the specification of a method parameter, i.e.
|
||||
* a {@link Method} or {@link Constructor} plus a parameter index and a nested
|
||||
* type index for a declared generic type. Useful as a specification object to
|
||||
* pass along.
|
||||
* Helper class that encapsulates the specification of a method parameter, i.e. a {@link Method}
|
||||
* or {@link Constructor} plus a parameter index and a nested type index for a declared generic
|
||||
* type. Useful as a specification object to pass along.
|
||||
*
|
||||
* <p>As of 4.2, there is a {@link org.springframework.core.annotation.SynthesizingMethodParameter
|
||||
* SynthesizingMethodParameter} subclass available which synthesizes annotations
|
||||
* with attribute aliases. That subclass is used for web and message endpoint
|
||||
* processing, in particular.
|
||||
* <p>As of 4.2, there is a {@link org.springframework.core.annotation.SynthesizingMethodParameter}
|
||||
* subclass available which synthesizes annotations with attribute aliases. That subclass is used
|
||||
* for web and message endpoint processing, in particular.
|
||||
*
|
||||
* @author Juergen Hoeller
|
||||
* @author Rob Harrop
|
||||
|
|
@ -49,6 +48,18 @@ import org.springframework.util.Assert;
|
|||
*/
|
||||
public class MethodParameter {
|
||||
|
||||
private static Class<?> javaUtilOptionalClass = null;
|
||||
|
||||
static {
|
||||
try {
|
||||
javaUtilOptionalClass = ClassUtils.forName("java.util.Optional", MethodParameter.class.getClassLoader());
|
||||
}
|
||||
catch (ClassNotFoundException ex) {
|
||||
// Java 8 not available - Optional references simply not supported then.
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private final Method method;
|
||||
|
||||
private final Constructor<?> constructor;
|
||||
|
|
@ -72,6 +83,8 @@ public class MethodParameter {
|
|||
|
||||
private volatile String parameterName;
|
||||
|
||||
private volatile MethodParameter nestedMethodParameter;
|
||||
|
||||
|
||||
/**
|
||||
* Create a new {@code MethodParameter} for the given method, with nesting level 1.
|
||||
|
|
@ -279,6 +292,44 @@ public class MethodParameter {
|
|||
return this.typeIndexesPerLevel;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a variant of this {@code MethodParameter} which points to the
|
||||
* same parameter but one nesting level deeper. This is effectively the
|
||||
* same as {@link #increaseNestingLevel()}, just with an independent
|
||||
* {@code MethodParameter} object (e.g. in case of the original being cached).
|
||||
* @since 4.3
|
||||
*/
|
||||
public MethodParameter nested() {
|
||||
if (this.nestedMethodParameter != null) {
|
||||
return this.nestedMethodParameter;
|
||||
}
|
||||
MethodParameter nestedParam = clone();
|
||||
nestedParam.nestingLevel = this.nestingLevel + 1;
|
||||
this.nestedMethodParameter = nestedParam;
|
||||
return nestedParam;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return whether this method parameter is declared as optiona
|
||||
* in the form of Java 8's {@link java.util.Optional}.
|
||||
* @since 4.3
|
||||
*/
|
||||
public boolean isOptional() {
|
||||
return (getParameterType() == javaUtilOptionalClass);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a variant of this {@code MethodParameter} which points to
|
||||
* the same parameter but one nesting level deeper in case of a
|
||||
* {@link java.util.Optional} declaration.
|
||||
* @since 4.3
|
||||
* @see #isOptional()
|
||||
* @see #nested()
|
||||
*/
|
||||
public MethodParameter nestedIfOptional() {
|
||||
return (isOptional() ? nested() : this);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Set a containing class to resolve the parameter type against.
|
||||
|
|
@ -370,8 +421,8 @@ public class MethodParameter {
|
|||
/**
|
||||
* Return the nested generic type of the method/constructor parameter.
|
||||
* @return the parameter type (never {@code null})
|
||||
* @see #getNestingLevel()
|
||||
* @since 4.2
|
||||
* @see #getNestingLevel()
|
||||
*/
|
||||
public Type getNestedGenericParameterType() {
|
||||
if (this.nestingLevel > 1) {
|
||||
|
|
@ -526,6 +577,11 @@ public class MethodParameter {
|
|||
return (getMember().hashCode() * 31 + this.parameterIndex);
|
||||
}
|
||||
|
||||
@Override
|
||||
public MethodParameter clone() {
|
||||
return new MethodParameter(this);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Create a new MethodParameter for the given method or constructor.
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2002-2015 the original author or authors.
|
||||
* Copyright 2002-2016 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.
|
||||
|
|
@ -44,6 +44,10 @@ public class SynthesizingMethodParameter extends MethodParameter {
|
|||
super(method, parameterIndex);
|
||||
}
|
||||
|
||||
protected SynthesizingMethodParameter(SynthesizingMethodParameter original) {
|
||||
super(original);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected <A extends Annotation> A adaptAnnotation(A annotation) {
|
||||
|
|
@ -55,4 +59,10 @@ public class SynthesizingMethodParameter extends MethodParameter {
|
|||
return AnnotationUtils.synthesizeAnnotationArray(annotations, getAnnotatedElement());
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public SynthesizingMethodParameter clone() {
|
||||
return new SynthesizingMethodParameter(this);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2002-2015 the original author or authors.
|
||||
* Copyright 2002-2016 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.
|
||||
|
|
@ -265,6 +265,10 @@ public class HandlerMethod {
|
|||
super(HandlerMethod.this.bridgedMethod, index);
|
||||
}
|
||||
|
||||
protected HandlerMethodParameter(HandlerMethodParameter original) {
|
||||
super(original);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<?> getContainingClass() {
|
||||
return HandlerMethod.this.getBeanType();
|
||||
|
|
@ -274,6 +278,11 @@ public class HandlerMethod {
|
|||
public <T extends Annotation> T getMethodAnnotation(Class<T> annotationType) {
|
||||
return HandlerMethod.this.getMethodAnnotation(annotationType);
|
||||
}
|
||||
|
||||
@Override
|
||||
public HandlerMethodParameter clone() {
|
||||
return new HandlerMethodParameter(this);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -289,10 +298,20 @@ public class HandlerMethod {
|
|||
this.returnValue = returnValue;
|
||||
}
|
||||
|
||||
protected ReturnValueMethodParameter(ReturnValueMethodParameter original) {
|
||||
super(original);
|
||||
this.returnValue = original.returnValue;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<?> getParameterType() {
|
||||
return (this.returnValue != null ? this.returnValue.getClass() : super.getParameterType());
|
||||
}
|
||||
|
||||
@Override
|
||||
public ReturnValueMethodParameter clone() {
|
||||
return new ReturnValueMethodParameter(this);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2002-2014 the original author or authors.
|
||||
* Copyright 2002-2016 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.
|
||||
|
|
@ -84,24 +84,24 @@ public abstract class AbstractNamedValueMethodArgumentResolver implements Handle
|
|||
|
||||
@Override
|
||||
public Object resolveArgument(MethodParameter parameter, Message<?> message) throws Exception {
|
||||
Class<?> paramType = parameter.getParameterType();
|
||||
NamedValueInfo namedValueInfo = getNamedValueInfo(parameter);
|
||||
MethodParameter nestedParameter = parameter.nestedIfOptional();
|
||||
|
||||
Object arg = resolveArgumentInternal(parameter, message, namedValueInfo.name);
|
||||
Object arg = resolveArgumentInternal(nestedParameter, message, namedValueInfo.name);
|
||||
if (arg == null) {
|
||||
if (namedValueInfo.defaultValue != null) {
|
||||
arg = resolveDefaultValue(namedValueInfo.defaultValue);
|
||||
}
|
||||
else if (namedValueInfo.required && !parameter.getParameterType().getName().equals("java.util.Optional")) {
|
||||
handleMissingValue(namedValueInfo.name, parameter, message);
|
||||
else if (namedValueInfo.required && !nestedParameter.isOptional()) {
|
||||
handleMissingValue(namedValueInfo.name, nestedParameter, message);
|
||||
}
|
||||
arg = handleNullValue(namedValueInfo.name, arg, paramType);
|
||||
arg = handleNullValue(namedValueInfo.name, arg, nestedParameter.getNestedParameterType());
|
||||
}
|
||||
else if ("".equals(arg) && namedValueInfo.defaultValue != null) {
|
||||
arg = resolveDefaultValue(namedValueInfo.defaultValue);
|
||||
}
|
||||
|
||||
if (!ClassUtils.isAssignableValue(paramType, arg)) {
|
||||
if (!ClassUtils.isAssignableValue(parameter.getParameterType(), arg)) {
|
||||
arg = this.conversionService.convert(
|
||||
arg, TypeDescriptor.valueOf(arg.getClass()), new TypeDescriptor(parameter));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2002-2013 the original author or authors.
|
||||
* Copyright 2002-2016 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.
|
||||
|
|
@ -42,6 +42,7 @@ public class DestinationVariableMethodArgumentResolver extends AbstractNamedValu
|
|||
super(cs, null);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean supportsParameter(MethodParameter parameter) {
|
||||
return parameter.hasParameterAnnotation(DestinationVariable.class);
|
||||
|
|
@ -58,10 +59,9 @@ public class DestinationVariableMethodArgumentResolver extends AbstractNamedValu
|
|||
throws Exception {
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
Map<String, String> vars = (Map<String, String>) message.getHeaders().get(
|
||||
DESTINATION_TEMPLATE_VARIABLES_HEADER);
|
||||
|
||||
return (vars != null) ? vars.get(name) : null;
|
||||
Map<String, String> vars =
|
||||
(Map<String, String>) message.getHeaders().get(DESTINATION_TEMPLATE_VARIABLES_HEADER);
|
||||
return (vars != null ? vars.get(name) : null);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
@ -77,4 +77,5 @@ public class DestinationVariableMethodArgumentResolver extends AbstractNamedValu
|
|||
super(annotation.value(), true, ValueConstants.DEFAULT_NONE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2002-2015 the original author or authors.
|
||||
* Copyright 2002-2016 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.
|
||||
|
|
@ -272,6 +272,12 @@ public class InvocableHandlerMethod extends HandlerMethod {
|
|||
this.returnType = ResolvableType.forType(super.getGenericParameterType()).getGeneric(0);
|
||||
}
|
||||
|
||||
protected AsyncResultMethodParameter(AsyncResultMethodParameter original) {
|
||||
super(original);
|
||||
this.returnValue = original.returnValue;
|
||||
this.returnType = original.returnType;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<?> getParameterType() {
|
||||
if (this.returnValue != null) {
|
||||
|
|
@ -287,6 +293,11 @@ public class InvocableHandlerMethod extends HandlerMethod {
|
|||
public Type getGenericParameterType() {
|
||||
return this.returnType.getType();
|
||||
}
|
||||
|
||||
@Override
|
||||
public AsyncResultMethodParameter clone() {
|
||||
return new AsyncResultMethodParameter(this);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2002-2015 the original author or authors.
|
||||
* Copyright 2002-2016 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.
|
||||
|
|
@ -55,7 +55,6 @@ import org.springframework.web.multipart.MultipartResolver;
|
|||
* @author Arjen Poutsma
|
||||
* @author Sam Brannen
|
||||
* @since 3.1
|
||||
*
|
||||
* @see RequestParam
|
||||
* @see org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2002-2015 the original author or authors.
|
||||
* Copyright 2002-2016 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.
|
||||
|
|
@ -280,6 +280,10 @@ public class HandlerMethod {
|
|||
super(HandlerMethod.this.bridgedMethod, index);
|
||||
}
|
||||
|
||||
protected HandlerMethodParameter(HandlerMethodParameter original) {
|
||||
super(original);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<?> getContainingClass() {
|
||||
return HandlerMethod.this.getBeanType();
|
||||
|
|
@ -289,6 +293,11 @@ public class HandlerMethod {
|
|||
public <T extends Annotation> T getMethodAnnotation(Class<T> annotationType) {
|
||||
return HandlerMethod.this.getMethodAnnotation(annotationType);
|
||||
}
|
||||
|
||||
@Override
|
||||
public HandlerMethodParameter clone() {
|
||||
return new HandlerMethodParameter(this);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -304,10 +313,20 @@ public class HandlerMethod {
|
|||
this.returnValue = returnValue;
|
||||
}
|
||||
|
||||
protected ReturnValueMethodParameter(ReturnValueMethodParameter original) {
|
||||
super(original);
|
||||
this.returnValue = original.returnValue;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<?> getParameterType() {
|
||||
return (this.returnValue != null ? this.returnValue.getClass() : super.getParameterType());
|
||||
}
|
||||
|
||||
@Override
|
||||
public ReturnValueMethodParameter clone() {
|
||||
return new ReturnValueMethodParameter(this);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2002-2015 the original author or authors.
|
||||
* Copyright 2002-2016 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.
|
||||
|
|
@ -63,7 +63,7 @@ public abstract class AbstractCookieValueMethodArgumentResolver extends Abstract
|
|||
@Override
|
||||
protected void handleMissingValue(String name, MethodParameter parameter) throws ServletRequestBindingException {
|
||||
throw new ServletRequestBindingException("Missing cookie '" + name +
|
||||
"' for method parameter of type " + parameter.getParameterType().getSimpleName());
|
||||
"' for method parameter of type " + parameter.getNestedParameterType().getSimpleName());
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2002-2015 the original author or authors.
|
||||
* Copyright 2002-2016 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,6 +26,7 @@ import org.springframework.beans.factory.config.BeanExpressionContext;
|
|||
import org.springframework.beans.factory.config.BeanExpressionResolver;
|
||||
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
|
||||
import org.springframework.core.MethodParameter;
|
||||
import org.springframework.web.bind.ServletRequestBindingException;
|
||||
import org.springframework.web.bind.WebDataBinder;
|
||||
import org.springframework.web.bind.annotation.ValueConstants;
|
||||
import org.springframework.web.bind.support.WebDataBinderFactory;
|
||||
|
|
@ -53,6 +54,7 @@ import org.springframework.web.method.support.ModelAndViewContainer;
|
|||
*
|
||||
* @author Arjen Poutsma
|
||||
* @author Rossen Stoyanchev
|
||||
* @author Juergen Hoeller
|
||||
* @since 3.1
|
||||
*/
|
||||
public abstract class AbstractNamedValueMethodArgumentResolver implements HandlerMethodArgumentResolver {
|
||||
|
|
@ -61,7 +63,7 @@ public abstract class AbstractNamedValueMethodArgumentResolver implements Handle
|
|||
|
||||
private final BeanExpressionContext expressionContext;
|
||||
|
||||
private Map<MethodParameter, NamedValueInfo> namedValueInfoCache = new ConcurrentHashMap<MethodParameter, NamedValueInfo>(256);
|
||||
private final Map<MethodParameter, NamedValueInfo> namedValueInfoCache = new ConcurrentHashMap<MethodParameter, NamedValueInfo>(256);
|
||||
|
||||
|
||||
public AbstractNamedValueMethodArgumentResolver() {
|
||||
|
|
@ -84,18 +86,18 @@ public abstract class AbstractNamedValueMethodArgumentResolver implements Handle
|
|||
public final Object resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer,
|
||||
NativeWebRequest webRequest, WebDataBinderFactory binderFactory) throws Exception {
|
||||
|
||||
Class<?> paramType = parameter.getParameterType();
|
||||
NamedValueInfo namedValueInfo = getNamedValueInfo(parameter);
|
||||
MethodParameter nestedParameter = parameter.nestedIfOptional();
|
||||
|
||||
Object arg = resolveName(namedValueInfo.name, parameter, webRequest);
|
||||
Object arg = resolveName(namedValueInfo.name, nestedParameter, webRequest);
|
||||
if (arg == null) {
|
||||
if (namedValueInfo.defaultValue != null) {
|
||||
arg = resolveDefaultValue(namedValueInfo.defaultValue);
|
||||
}
|
||||
else if (namedValueInfo.required && !parameter.getParameterType().getName().equals("java.util.Optional")) {
|
||||
handleMissingValue(namedValueInfo.name, parameter);
|
||||
else if (namedValueInfo.required && !nestedParameter.isOptional()) {
|
||||
handleMissingValue(namedValueInfo.name, nestedParameter, webRequest);
|
||||
}
|
||||
arg = handleNullValue(namedValueInfo.name, arg, paramType);
|
||||
arg = handleNullValue(namedValueInfo.name, arg, nestedParameter.getNestedParameterType());
|
||||
}
|
||||
else if ("".equals(arg) && namedValueInfo.defaultValue != null) {
|
||||
arg = resolveDefaultValue(namedValueInfo.defaultValue);
|
||||
|
|
@ -104,7 +106,7 @@ public abstract class AbstractNamedValueMethodArgumentResolver implements Handle
|
|||
if (binderFactory != null) {
|
||||
WebDataBinder binder = binderFactory.createBinder(webRequest, null, namedValueInfo.name);
|
||||
try {
|
||||
arg = binder.convertIfNecessary(arg, paramType, parameter);
|
||||
arg = binder.convertIfNecessary(arg, parameter.getParameterType(), parameter);
|
||||
}
|
||||
catch (ConversionNotSupportedException ex) {
|
||||
throw new MethodArgumentConversionNotSupportedException(arg, ex.getRequiredType(),
|
||||
|
|
@ -151,7 +153,8 @@ public abstract class AbstractNamedValueMethodArgumentResolver implements Handle
|
|||
if (info.name.length() == 0) {
|
||||
name = parameter.getParameterName();
|
||||
if (name == null) {
|
||||
throw new IllegalArgumentException("Name for argument type [" + parameter.getParameterType().getName() +
|
||||
throw new IllegalArgumentException(
|
||||
"Name for argument type [" + parameter.getNestedParameterType().getName() +
|
||||
"] not available, and parameter name information not found in class file either.");
|
||||
}
|
||||
}
|
||||
|
|
@ -160,18 +163,19 @@ public abstract class AbstractNamedValueMethodArgumentResolver implements Handle
|
|||
}
|
||||
|
||||
/**
|
||||
* Resolves the given parameter type and value name into an argument value.
|
||||
* Resolve the given parameter type and value name into an argument value.
|
||||
* @param name the name of the value being resolved
|
||||
* @param parameter the method parameter to resolve to an argument value
|
||||
* (pre-nested in case of a {@link java.util.Optional} declaration)
|
||||
* @param request the current request
|
||||
* @return the resolved argument. May be {@code null}
|
||||
* @return the resolved argument (may be {@code null})
|
||||
* @throws Exception in case of errors
|
||||
*/
|
||||
protected abstract Object resolveName(String name, MethodParameter parameter, NativeWebRequest request)
|
||||
throws Exception;
|
||||
|
||||
/**
|
||||
* Resolves the given default value into an argument value.
|
||||
* Resolve the given default value into an argument value.
|
||||
*/
|
||||
private Object resolveDefaultValue(String defaultValue) {
|
||||
if (this.configurableBeanFactory == null) {
|
||||
|
|
@ -190,8 +194,23 @@ public abstract class AbstractNamedValueMethodArgumentResolver implements Handle
|
|||
* returned {@code null} and there is no default value. Subclasses typically throw an exception in this case.
|
||||
* @param name the name for the value
|
||||
* @param parameter the method parameter
|
||||
* @param request the current request
|
||||
* @since 4.3
|
||||
*/
|
||||
protected abstract void handleMissingValue(String name, MethodParameter parameter) throws ServletException;
|
||||
protected void handleMissingValue(String name, MethodParameter parameter, NativeWebRequest request) throws Exception {
|
||||
handleMissingValue(name, parameter);
|
||||
}
|
||||
|
||||
/**
|
||||
* Invoked when a named value is required, but {@link #resolveName(String, MethodParameter, NativeWebRequest)}
|
||||
* returned {@code null} and there is no default value. Subclasses typically throw an exception in this case.
|
||||
* @param name the name for the value
|
||||
* @param parameter the method parameter
|
||||
*/
|
||||
protected void handleMissingValue(String name, MethodParameter parameter) throws ServletException {
|
||||
throw new ServletRequestBindingException("Missing argument '" + name +
|
||||
"' for method parameter of type " + parameter.getNestedParameterType().getSimpleName());
|
||||
}
|
||||
|
||||
/**
|
||||
* A {@code null} results in a {@code false} value for {@code boolean}s or an exception for other primitives.
|
||||
|
|
@ -202,7 +221,7 @@ public abstract class AbstractNamedValueMethodArgumentResolver implements Handle
|
|||
return Boolean.FALSE;
|
||||
}
|
||||
else if (paramType.isPrimitive()) {
|
||||
throw new IllegalStateException("Optional " + paramType + " parameter '" + name +
|
||||
throw new IllegalStateException("Optional " + paramType.getSimpleName() + " parameter '" + name +
|
||||
"' is present but cannot be translated into a null value due to being declared as a " +
|
||||
"primitive type. Consider declaring it as object wrapper for the corresponding primitive type.");
|
||||
}
|
||||
|
|
|
|||
|
|
@ -56,7 +56,7 @@ public class RequestHeaderMethodArgumentResolver extends AbstractNamedValueMetho
|
|||
@Override
|
||||
public boolean supportsParameter(MethodParameter parameter) {
|
||||
return (parameter.hasParameterAnnotation(RequestHeader.class) &&
|
||||
!Map.class.isAssignableFrom(parameter.getParameterType()));
|
||||
!Map.class.isAssignableFrom(parameter.nestedIfOptional().getNestedParameterType()));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
@ -79,7 +79,7 @@ public class RequestHeaderMethodArgumentResolver extends AbstractNamedValueMetho
|
|||
@Override
|
||||
protected void handleMissingValue(String name, MethodParameter parameter) throws ServletRequestBindingException {
|
||||
throw new ServletRequestBindingException("Missing request header '" + name +
|
||||
"' for method parameter of type " + parameter.getParameterType().getSimpleName());
|
||||
"' for method parameter of type " + parameter.getNestedParameterType().getSimpleName());
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2002-2015 the original author or authors.
|
||||
* Copyright 2002-2016 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.
|
||||
|
|
@ -17,22 +17,17 @@
|
|||
package org.springframework.web.method.annotation;
|
||||
|
||||
import java.beans.PropertyEditor;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.Part;
|
||||
|
||||
import org.springframework.beans.BeanUtils;
|
||||
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
|
||||
import org.springframework.core.GenericCollectionTypeResolver;
|
||||
import org.springframework.core.MethodParameter;
|
||||
import org.springframework.core.convert.ConversionService;
|
||||
import org.springframework.core.convert.TypeDescriptor;
|
||||
import org.springframework.core.convert.converter.Converter;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.StringUtils;
|
||||
import org.springframework.web.bind.MissingServletRequestParameterException;
|
||||
import org.springframework.web.bind.WebDataBinder;
|
||||
|
|
@ -45,6 +40,8 @@ import org.springframework.web.multipart.MultipartException;
|
|||
import org.springframework.web.multipart.MultipartFile;
|
||||
import org.springframework.web.multipart.MultipartHttpServletRequest;
|
||||
import org.springframework.web.multipart.MultipartResolver;
|
||||
import org.springframework.web.multipart.support.MissingServletRequestPartException;
|
||||
import org.springframework.web.multipart.support.MultipartResolutionDelegate;
|
||||
import org.springframework.web.util.UriComponentsBuilder;
|
||||
import org.springframework.web.util.WebUtils;
|
||||
|
||||
|
|
@ -124,9 +121,8 @@ public class RequestParamMethodArgumentResolver extends AbstractNamedValueMethod
|
|||
*/
|
||||
@Override
|
||||
public boolean supportsParameter(MethodParameter parameter) {
|
||||
Class<?> paramType = parameter.getParameterType();
|
||||
if (parameter.hasParameterAnnotation(RequestParam.class)) {
|
||||
if (Map.class.isAssignableFrom(paramType)) {
|
||||
if (Map.class.isAssignableFrom(parameter.nestedIfOptional().getNestedParameterType())) {
|
||||
String paramName = parameter.getParameterAnnotation(RequestParam.class).name();
|
||||
return StringUtils.hasText(paramName);
|
||||
}
|
||||
|
|
@ -138,11 +134,12 @@ public class RequestParamMethodArgumentResolver extends AbstractNamedValueMethod
|
|||
if (parameter.hasParameterAnnotation(RequestPart.class)) {
|
||||
return false;
|
||||
}
|
||||
else if (MultipartFile.class == paramType || "javax.servlet.http.Part".equals(paramType.getName())) {
|
||||
parameter = parameter.nestedIfOptional();
|
||||
if (MultipartResolutionDelegate.isMultipartArgument(parameter)) {
|
||||
return true;
|
||||
}
|
||||
else if (this.useDefaultResolution) {
|
||||
return BeanUtils.isSimpleProperty(paramType);
|
||||
return BeanUtils.isSimpleProperty(parameter.getNestedParameterType());
|
||||
}
|
||||
else {
|
||||
return false;
|
||||
|
|
@ -157,112 +154,61 @@ public class RequestParamMethodArgumentResolver extends AbstractNamedValueMethod
|
|||
}
|
||||
|
||||
@Override
|
||||
protected Object resolveName(String name, MethodParameter parameter, NativeWebRequest webRequest) throws Exception {
|
||||
HttpServletRequest servletRequest = webRequest.getNativeRequest(HttpServletRequest.class);
|
||||
protected Object resolveName(String name, MethodParameter parameter, NativeWebRequest request) throws Exception {
|
||||
HttpServletRequest servletRequest = request.getNativeRequest(HttpServletRequest.class);
|
||||
MultipartHttpServletRequest multipartRequest =
|
||||
WebUtils.getNativeRequest(servletRequest, MultipartHttpServletRequest.class);
|
||||
Object arg;
|
||||
|
||||
if (MultipartFile.class == parameter.getParameterType()) {
|
||||
assertIsMultipartRequest(servletRequest);
|
||||
Assert.notNull(multipartRequest, "Expected MultipartHttpServletRequest: is a MultipartResolver configured?");
|
||||
arg = multipartRequest.getFile(name);
|
||||
}
|
||||
else if (isMultipartFileCollection(parameter)) {
|
||||
assertIsMultipartRequest(servletRequest);
|
||||
Assert.notNull(multipartRequest, "Expected MultipartHttpServletRequest: is a MultipartResolver configured?");
|
||||
arg = multipartRequest.getFiles(name);
|
||||
}
|
||||
else if (isMultipartFileArray(parameter)) {
|
||||
assertIsMultipartRequest(servletRequest);
|
||||
Assert.notNull(multipartRequest, "Expected MultipartHttpServletRequest: is a MultipartResolver configured?");
|
||||
List<MultipartFile> multipartFiles = multipartRequest.getFiles(name);
|
||||
arg = multipartFiles.toArray(new MultipartFile[multipartFiles.size()]);
|
||||
}
|
||||
else if ("javax.servlet.http.Part".equals(parameter.getParameterType().getName())) {
|
||||
assertIsMultipartRequest(servletRequest);
|
||||
arg = servletRequest.getPart(name);
|
||||
}
|
||||
else if (isPartCollection(parameter)) {
|
||||
assertIsMultipartRequest(servletRequest);
|
||||
arg = new ArrayList<Object>(servletRequest.getParts());
|
||||
}
|
||||
else if (isPartArray(parameter)) {
|
||||
assertIsMultipartRequest(servletRequest);
|
||||
arg = RequestPartResolver.resolvePart(servletRequest);
|
||||
}
|
||||
else {
|
||||
arg = null;
|
||||
if (multipartRequest != null) {
|
||||
List<MultipartFile> files = multipartRequest.getFiles(name);
|
||||
if (!files.isEmpty()) {
|
||||
arg = (files.size() == 1 ? files.get(0) : files);
|
||||
}
|
||||
}
|
||||
if (arg == null) {
|
||||
String[] paramValues = webRequest.getParameterValues(name);
|
||||
if (paramValues != null) {
|
||||
arg = (paramValues.length == 1 ? paramValues[0] : paramValues);
|
||||
}
|
||||
}
|
||||
Object mpArg = MultipartResolutionDelegate.resolveMultipartArgument(name, parameter, servletRequest);
|
||||
if (mpArg != MultipartResolutionDelegate.UNRESOLVABLE) {
|
||||
return mpArg;
|
||||
}
|
||||
|
||||
Object arg = null;
|
||||
if (multipartRequest != null) {
|
||||
List<MultipartFile> files = multipartRequest.getFiles(name);
|
||||
if (!files.isEmpty()) {
|
||||
arg = (files.size() == 1 ? files.get(0) : files);
|
||||
}
|
||||
}
|
||||
if (arg == null) {
|
||||
String[] paramValues = request.getParameterValues(name);
|
||||
if (paramValues != null) {
|
||||
arg = (paramValues.length == 1 ? paramValues[0] : paramValues);
|
||||
}
|
||||
}
|
||||
return arg;
|
||||
}
|
||||
|
||||
private void assertIsMultipartRequest(HttpServletRequest request) {
|
||||
String contentType = request.getContentType();
|
||||
if (contentType == null || !contentType.toLowerCase().startsWith("multipart/")) {
|
||||
throw new MultipartException("The current request is not a multipart request");
|
||||
}
|
||||
}
|
||||
|
||||
private boolean isMultipartFileCollection(MethodParameter parameter) {
|
||||
return (MultipartFile.class == getCollectionParameterType(parameter));
|
||||
}
|
||||
|
||||
private boolean isMultipartFileArray(MethodParameter parameter) {
|
||||
return (MultipartFile.class == parameter.getParameterType().getComponentType());
|
||||
}
|
||||
|
||||
private boolean isPartCollection(MethodParameter parameter) {
|
||||
Class<?> collectionType = getCollectionParameterType(parameter);
|
||||
return (collectionType != null && "javax.servlet.http.Part".equals(collectionType.getName()));
|
||||
}
|
||||
|
||||
private boolean isPartArray(MethodParameter parameter) {
|
||||
Class<?> paramType = parameter.getParameterType().getComponentType();
|
||||
return (paramType != null && "javax.servlet.http.Part".equals(paramType.getName()));
|
||||
}
|
||||
|
||||
private Class<?> getCollectionParameterType(MethodParameter parameter) {
|
||||
Class<?> paramType = parameter.getParameterType();
|
||||
if (Collection.class == paramType || List.class.isAssignableFrom(paramType)){
|
||||
Class<?> valueType = GenericCollectionTypeResolver.getCollectionParameterType(parameter);
|
||||
if (valueType != null) {
|
||||
return valueType;
|
||||
@Override
|
||||
protected void handleMissingValue(String name, MethodParameter parameter, NativeWebRequest request) throws Exception {
|
||||
HttpServletRequest servletRequest = request.getNativeRequest(HttpServletRequest.class);
|
||||
if (MultipartResolutionDelegate.isMultipartArgument(parameter)) {
|
||||
if (!MultipartResolutionDelegate.isMultipartRequest(servletRequest)) {
|
||||
throw new MultipartException("Current request is not a multipart request");
|
||||
}
|
||||
else {
|
||||
throw new MissingServletRequestPartException(name);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void handleMissingValue(String name, MethodParameter parameter) throws ServletException {
|
||||
throw new MissingServletRequestParameterException(name, parameter.getParameterType().getSimpleName());
|
||||
else {
|
||||
throw new MissingServletRequestParameterException(name, parameter.getNestedParameterType().getSimpleName());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void contributeMethodArgument(MethodParameter parameter, Object value,
|
||||
UriComponentsBuilder builder, Map<String, Object> uriVariables, ConversionService conversionService) {
|
||||
|
||||
Class<?> paramType = parameter.getParameterType();
|
||||
Class<?> paramType = parameter.getNestedParameterType();
|
||||
if (Map.class.isAssignableFrom(paramType) || MultipartFile.class == paramType ||
|
||||
"javax.servlet.http.Part".equals(paramType.getName())) {
|
||||
return;
|
||||
}
|
||||
|
||||
RequestParam requestParam = parameter.getParameterAnnotation(RequestParam.class);
|
||||
String name = (requestParam == null || StringUtils.isEmpty(requestParam.name()) ? parameter.getParameterName() : requestParam.name());
|
||||
String name = (requestParam == null || StringUtils.isEmpty(requestParam.name()) ?
|
||||
parameter.getParameterName() : requestParam.name());
|
||||
|
||||
if (value == null) {
|
||||
builder.queryParam(name);
|
||||
|
|
@ -305,12 +251,4 @@ public class RequestParamMethodArgumentResolver extends AbstractNamedValueMethod
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
private static class RequestPartResolver {
|
||||
|
||||
public static Object resolvePart(HttpServletRequest servletRequest) throws Exception {
|
||||
return servletRequest.getParts().toArray(new Part[servletRequest.getParts().size()]);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2002-2011 the original author or authors.
|
||||
* Copyright 2002-2016 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.
|
||||
|
|
@ -24,27 +24,28 @@ import org.springframework.web.multipart.MultipartResolver;
|
|||
* Raised when the part of a "multipart/form-data" request identified by its
|
||||
* name cannot be found.
|
||||
*
|
||||
* <p>This may be because the request is not a multipart/form-data
|
||||
*
|
||||
* either because the part is not present in the request, or
|
||||
* because the web application is not configured correctly for processing
|
||||
* multipart requests -- e.g. no {@link MultipartResolver}.
|
||||
* <p>This may be because the request is not a multipart/form-data request,
|
||||
* because the part is not present in the request, or because the web
|
||||
* application is not configured correctly for processing multipart requests,
|
||||
* e.g. no {@link MultipartResolver}.
|
||||
*
|
||||
* @author Rossen Stoyanchev
|
||||
* @since 3.1
|
||||
*/
|
||||
@SuppressWarnings("serial")
|
||||
public class MissingServletRequestPartException extends ServletException {
|
||||
|
||||
private static final long serialVersionUID = -1255077391966870705L;
|
||||
|
||||
private final String partName;
|
||||
|
||||
|
||||
public MissingServletRequestPartException(String partName) {
|
||||
super("Required request part '" + partName + "' is not present.");
|
||||
super("Required request part '" + partName + "' is not present");
|
||||
this.partName = partName;
|
||||
}
|
||||
|
||||
|
||||
public String getRequestPartName() {
|
||||
return this.partName;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,197 @@
|
|||
/*
|
||||
* Copyright 2002-2016 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.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.web.multipart.support;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.Part;
|
||||
|
||||
import org.springframework.core.GenericCollectionTypeResolver;
|
||||
import org.springframework.core.MethodParameter;
|
||||
import org.springframework.util.ClassUtils;
|
||||
import org.springframework.web.multipart.MultipartException;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
import org.springframework.web.multipart.MultipartHttpServletRequest;
|
||||
import org.springframework.web.util.WebUtils;
|
||||
|
||||
/**
|
||||
* A common delegate for {@code HandlerMethodArgumentResolver} implementations
|
||||
* which need to resolve {@link MultipartFile} and {@link Part} arguments.
|
||||
*
|
||||
* @author Juergen Hoeller
|
||||
* @since 4.3
|
||||
*/
|
||||
public abstract class MultipartResolutionDelegate {
|
||||
|
||||
public static final Object UNRESOLVABLE = new Object();
|
||||
|
||||
|
||||
private static Class<?> servletPartClass = null;
|
||||
|
||||
static {
|
||||
try {
|
||||
servletPartClass = ClassUtils.forName(
|
||||
"javax.servlet.http.Part", MultipartResolutionDelegate.class.getClassLoader());
|
||||
}
|
||||
catch (ClassNotFoundException ex) {
|
||||
// Servlet 3.0 Part type not available - Part references simply not supported then.
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static boolean isMultipartRequest(HttpServletRequest request) {
|
||||
return (WebUtils.getNativeRequest(request, MultipartHttpServletRequest.class) != null ||
|
||||
isMultipartContent(request));
|
||||
}
|
||||
|
||||
private static boolean isMultipartContent(HttpServletRequest request) {
|
||||
String contentType = request.getContentType();
|
||||
return (contentType != null && contentType.toLowerCase().startsWith("multipart/"));
|
||||
}
|
||||
|
||||
static MultipartHttpServletRequest asMultipartHttpServletRequest(HttpServletRequest request) {
|
||||
MultipartHttpServletRequest unwrapped = WebUtils.getNativeRequest(request, MultipartHttpServletRequest.class);
|
||||
if (unwrapped != null) {
|
||||
return unwrapped;
|
||||
}
|
||||
return adaptToMultipartHttpServletRequest(request);
|
||||
}
|
||||
|
||||
private static MultipartHttpServletRequest adaptToMultipartHttpServletRequest(HttpServletRequest request) {
|
||||
if (servletPartClass != null) {
|
||||
// Servlet 3.0 available ..
|
||||
return new StandardMultipartHttpServletRequest(request);
|
||||
}
|
||||
throw new MultipartException("Expected MultipartHttpServletRequest: is a MultipartResolver configured?");
|
||||
}
|
||||
|
||||
|
||||
public static boolean isMultipartArgument(MethodParameter parameter) {
|
||||
Class<?> paramType = parameter.getNestedParameterType();
|
||||
return (MultipartFile.class == paramType || isMultipartFileCollection(parameter) ||
|
||||
isMultipartFileArray(parameter) || servletPartClass == paramType ||
|
||||
isPartCollection(parameter) || isPartArray(parameter));
|
||||
}
|
||||
|
||||
public static Object resolveMultipartArgument(String name, MethodParameter parameter, HttpServletRequest request)
|
||||
throws Exception {
|
||||
|
||||
MultipartHttpServletRequest multipartRequest =
|
||||
WebUtils.getNativeRequest(request, MultipartHttpServletRequest.class);
|
||||
boolean isMultipart = (multipartRequest != null || isMultipartContent(request));
|
||||
|
||||
if (MultipartFile.class == parameter.getNestedParameterType()) {
|
||||
if (multipartRequest == null && isMultipart) {
|
||||
multipartRequest = adaptToMultipartHttpServletRequest(request);
|
||||
}
|
||||
return (multipartRequest != null ? multipartRequest.getFile(name) : null);
|
||||
}
|
||||
else if (isMultipartFileCollection(parameter)) {
|
||||
if (multipartRequest == null && isMultipart) {
|
||||
multipartRequest = adaptToMultipartHttpServletRequest(request);
|
||||
}
|
||||
return (multipartRequest != null ? multipartRequest.getFiles(name) : null);
|
||||
}
|
||||
else if (isMultipartFileArray(parameter)) {
|
||||
if (multipartRequest == null && isMultipart) {
|
||||
multipartRequest = adaptToMultipartHttpServletRequest(request);
|
||||
}
|
||||
if (multipartRequest != null) {
|
||||
List<MultipartFile> multipartFiles = multipartRequest.getFiles(name);
|
||||
return multipartFiles.toArray(new MultipartFile[multipartFiles.size()]);
|
||||
}
|
||||
else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
else if (parameter.getNestedParameterType() == servletPartClass) {
|
||||
return (isMultipart ? RequestPartResolver.resolvePart(request, name) : null);
|
||||
}
|
||||
else if (isPartCollection(parameter)) {
|
||||
return (isMultipart ? RequestPartResolver.resolvePartList(request, name) : null);
|
||||
}
|
||||
else if (isPartArray(parameter)) {
|
||||
return (isMultipart ? RequestPartResolver.resolvePartArray(request, name) : null);
|
||||
}
|
||||
else {
|
||||
return UNRESOLVABLE;
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean isMultipartFileCollection(MethodParameter methodParam) {
|
||||
return (MultipartFile.class == getCollectionParameterType(methodParam));
|
||||
}
|
||||
|
||||
private static boolean isMultipartFileArray(MethodParameter methodParam) {
|
||||
return (MultipartFile.class == methodParam.getNestedParameterType().getComponentType());
|
||||
}
|
||||
|
||||
private static boolean isPartCollection(MethodParameter methodParam) {
|
||||
return (servletPartClass == getCollectionParameterType(methodParam));
|
||||
}
|
||||
|
||||
private static boolean isPartArray(MethodParameter methodParam) {
|
||||
return (servletPartClass == methodParam.getNestedParameterType().getComponentType());
|
||||
}
|
||||
|
||||
private static Class<?> getCollectionParameterType(MethodParameter methodParam) {
|
||||
Class<?> paramType = methodParam.getNestedParameterType();
|
||||
if (Collection.class == paramType || List.class.isAssignableFrom(paramType)){
|
||||
Class<?> valueType = GenericCollectionTypeResolver.getCollectionParameterType(methodParam);
|
||||
if (valueType != null) {
|
||||
return valueType;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Inner class to avoid hard-coded dependency on Servlet 3.0 Part type...
|
||||
*/
|
||||
private static class RequestPartResolver {
|
||||
|
||||
public static Object resolvePart(HttpServletRequest servletRequest, String name) throws Exception {
|
||||
return servletRequest.getPart(name);
|
||||
}
|
||||
|
||||
public static Object resolvePartList(HttpServletRequest servletRequest, String name) throws Exception {
|
||||
Collection<Part> parts = servletRequest.getParts();
|
||||
List<Part> result = new ArrayList<Part>(parts.size());
|
||||
for (Part part : parts) {
|
||||
if (part.getName().equals(name)) {
|
||||
result.add(part);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public static Object resolvePartArray(HttpServletRequest servletRequest, String name) throws Exception {
|
||||
Collection<Part> parts = servletRequest.getParts();
|
||||
List<Part> result = new ArrayList<Part>(parts.size());
|
||||
for (Part part : parts) {
|
||||
if (part.getName().equals(name)) {
|
||||
result.add(part);
|
||||
}
|
||||
}
|
||||
return result.toArray(new Part[result.size()]);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2002-2015 the original author or authors.
|
||||
* Copyright 2002-2016 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,13 +26,10 @@ import org.springframework.http.HttpHeaders;
|
|||
import org.springframework.http.MediaType;
|
||||
import org.springframework.http.server.ServerHttpRequest;
|
||||
import org.springframework.http.server.ServletServerHttpRequest;
|
||||
import org.springframework.util.ClassUtils;
|
||||
import org.springframework.web.multipart.MultipartException;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
import org.springframework.web.multipart.MultipartHttpServletRequest;
|
||||
import org.springframework.web.multipart.MultipartResolver;
|
||||
import org.springframework.web.util.WebUtils;
|
||||
|
||||
|
||||
/**
|
||||
* {@link ServerHttpRequest} implementation that accesses one part of a multipart
|
||||
|
|
@ -54,46 +51,26 @@ public class RequestPartServletServerHttpRequest extends ServletServerHttpReques
|
|||
|
||||
|
||||
/**
|
||||
* Create a new instance.
|
||||
* @param request the current request
|
||||
* Create a new {@code RequestPartServletServerHttpRequest} instance.
|
||||
* @param request the current servlet request
|
||||
* @param partName the name of the part to adapt to the {@link ServerHttpRequest} contract
|
||||
* @throws MissingServletRequestPartException if the request part cannot be found
|
||||
* @throws IllegalArgumentException if MultipartHttpServletRequest cannot be initialized
|
||||
* @throws MultipartException if MultipartHttpServletRequest cannot be initialized
|
||||
*/
|
||||
public RequestPartServletServerHttpRequest(HttpServletRequest request, String partName)
|
||||
throws MissingServletRequestPartException {
|
||||
|
||||
super(request);
|
||||
|
||||
this.multipartRequest = asMultipartRequest(request);
|
||||
this.multipartRequest = MultipartResolutionDelegate.asMultipartHttpServletRequest(request);
|
||||
this.partName = partName;
|
||||
|
||||
this.headers = this.multipartRequest.getMultipartHeaders(this.partName);
|
||||
if (this.headers == null) {
|
||||
if (request instanceof MultipartHttpServletRequest) {
|
||||
throw new MissingServletRequestPartException(partName);
|
||||
}
|
||||
else {
|
||||
throw new IllegalArgumentException(
|
||||
"Failed to obtain request part: " + partName + ". " +
|
||||
"The part is missing or multipart processing is not configured. " +
|
||||
"Check for a MultipartResolver bean or if Servlet 3.0 multipart processing is enabled.");
|
||||
}
|
||||
throw new MissingServletRequestPartException(partName);
|
||||
}
|
||||
}
|
||||
|
||||
private static MultipartHttpServletRequest asMultipartRequest(HttpServletRequest request) {
|
||||
MultipartHttpServletRequest unwrapped = WebUtils.getNativeRequest(request, MultipartHttpServletRequest.class);
|
||||
if (unwrapped != null) {
|
||||
return unwrapped;
|
||||
}
|
||||
else if (ClassUtils.hasMethod(HttpServletRequest.class, "getParts")) {
|
||||
// Servlet 3.0 available ..
|
||||
return new StandardMultipartHttpServletRequest(request);
|
||||
}
|
||||
throw new IllegalArgumentException("Expected MultipartHttpServletRequest: is a MultipartResolver configured?");
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public HttpHeaders getHeaders() {
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2002-2015 the original author or authors.
|
||||
* Copyright 2002-2016 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.
|
||||
|
|
@ -37,6 +37,7 @@ import org.springframework.mock.web.test.MockHttpServletResponse;
|
|||
import org.springframework.mock.web.test.MockMultipartFile;
|
||||
import org.springframework.mock.web.test.MockMultipartHttpServletRequest;
|
||||
import org.springframework.mock.web.test.MockPart;
|
||||
import org.springframework.util.ReflectionUtils;
|
||||
import org.springframework.web.bind.MissingServletRequestParameterException;
|
||||
import org.springframework.web.bind.WebDataBinder;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
|
|
@ -49,6 +50,7 @@ import org.springframework.web.context.request.NativeWebRequest;
|
|||
import org.springframework.web.context.request.ServletWebRequest;
|
||||
import org.springframework.web.multipart.MultipartException;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
import org.springframework.web.multipart.support.MissingServletRequestPartException;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
import static org.mockito.BDDMockito.*;
|
||||
|
|
@ -82,22 +84,18 @@ public class RequestParamMethodArgumentResolverTests {
|
|||
private MethodParameter paramRequired;
|
||||
private MethodParameter paramNotRequired;
|
||||
private MethodParameter paramOptional;
|
||||
private MethodParameter multipartFileOptional;
|
||||
|
||||
private NativeWebRequest webRequest;
|
||||
|
||||
private MockHttpServletRequest request;
|
||||
|
||||
|
||||
@Before
|
||||
public void setUp() throws Exception {
|
||||
resolver = new RequestParamMethodArgumentResolver(null, true);
|
||||
|
||||
ParameterNameDiscoverer paramNameDiscoverer = new LocalVariableTableParameterNameDiscoverer();
|
||||
|
||||
Method method = getClass().getMethod("params", String.class, String[].class,
|
||||
Map.class, MultipartFile.class, List.class, MultipartFile[].class,
|
||||
Part.class, List.class, Part[].class, Map.class,
|
||||
String.class, MultipartFile.class, List.class, Part.class,
|
||||
MultipartFile.class, String.class, String.class, Optional.class);
|
||||
Method method = ReflectionUtils.findMethod(getClass(), "handle", (Class<?>[]) null);
|
||||
|
||||
paramNamedDefaultValueString = new SynthesizingMethodParameter(method, 0);
|
||||
paramNamedStringArray = new SynthesizingMethodParameter(method, 1);
|
||||
|
|
@ -121,27 +119,35 @@ public class RequestParamMethodArgumentResolverTests {
|
|||
paramRequired = new SynthesizingMethodParameter(method, 15);
|
||||
paramNotRequired = new SynthesizingMethodParameter(method, 16);
|
||||
paramOptional = new SynthesizingMethodParameter(method, 17);
|
||||
multipartFileOptional = new SynthesizingMethodParameter(method, 18);
|
||||
|
||||
request = new MockHttpServletRequest();
|
||||
webRequest = new ServletWebRequest(request, new MockHttpServletResponse());
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void supportsParameter() {
|
||||
resolver = new RequestParamMethodArgumentResolver(null, true);
|
||||
assertTrue("String parameter not supported", resolver.supportsParameter(paramNamedDefaultValueString));
|
||||
assertTrue("String array parameter not supported", resolver.supportsParameter(paramNamedStringArray));
|
||||
assertTrue("Named map not parameter supported", resolver.supportsParameter(paramNamedMap));
|
||||
assertTrue("MultipartFile parameter not supported", resolver.supportsParameter(paramMultipartFile));
|
||||
assertTrue("List<MultipartFile> parameter not supported", resolver.supportsParameter(paramMultipartFileList));
|
||||
assertTrue("MultipartFile[] parameter not supported", resolver.supportsParameter(paramMultipartFileArray));
|
||||
assertTrue("Part parameter not supported", resolver.supportsParameter(paramPart));
|
||||
assertTrue("List<Part> parameter not supported", resolver.supportsParameter(paramPartList));
|
||||
assertTrue("Part[] parameter not supported", resolver.supportsParameter(paramPartArray));
|
||||
assertFalse("non-@RequestParam parameter supported", resolver.supportsParameter(paramMap));
|
||||
assertTrue("Simple type params supported w/o annotations", resolver.supportsParameter(paramStringNotAnnot));
|
||||
assertTrue("MultipartFile parameter not supported", resolver.supportsParameter(paramMultipartFileNotAnnot));
|
||||
assertTrue("Part parameter not supported", resolver.supportsParameter(paramPartNotAnnot));
|
||||
assertTrue(resolver.supportsParameter(paramNamedDefaultValueString));
|
||||
assertTrue(resolver.supportsParameter(paramNamedStringArray));
|
||||
assertTrue(resolver.supportsParameter(paramNamedMap));
|
||||
assertTrue(resolver.supportsParameter(paramMultipartFile));
|
||||
assertTrue(resolver.supportsParameter(paramMultipartFileList));
|
||||
assertTrue(resolver.supportsParameter(paramMultipartFileArray));
|
||||
assertTrue(resolver.supportsParameter(paramPart));
|
||||
assertTrue(resolver.supportsParameter(paramPartList));
|
||||
assertTrue(resolver.supportsParameter(paramPartArray));
|
||||
assertFalse(resolver.supportsParameter(paramMap));
|
||||
assertTrue(resolver.supportsParameter(paramStringNotAnnot));
|
||||
assertTrue(resolver.supportsParameter(paramMultipartFileNotAnnot));
|
||||
assertTrue(resolver.supportsParameter(paramMultipartFileListNotAnnot));
|
||||
assertTrue(resolver.supportsParameter(paramPartNotAnnot));
|
||||
assertFalse(resolver.supportsParameter(paramRequestPartAnnot));
|
||||
assertTrue(resolver.supportsParameter(paramRequired));
|
||||
assertTrue(resolver.supportsParameter(paramNotRequired));
|
||||
assertTrue(resolver.supportsParameter(paramOptional));
|
||||
assertTrue(resolver.supportsParameter(multipartFileOptional));
|
||||
|
||||
resolver = new RequestParamMethodArgumentResolver(null, false);
|
||||
assertFalse(resolver.supportsParameter(paramStringNotAnnot));
|
||||
|
|
@ -154,18 +160,16 @@ public class RequestParamMethodArgumentResolverTests {
|
|||
request.addParameter("name", expected);
|
||||
|
||||
Object result = resolver.resolveArgument(paramNamedDefaultValueString, null, webRequest, null);
|
||||
|
||||
assertTrue(result instanceof String);
|
||||
assertEquals("Invalid result", expected, result);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void resolveStringArray() throws Exception {
|
||||
String[] expected = new String[]{"foo", "bar"};
|
||||
String[] expected = new String[] {"foo", "bar"};
|
||||
request.addParameter("name", expected);
|
||||
|
||||
Object result = resolver.resolveArgument(paramNamedStringArray, null, webRequest, null);
|
||||
|
||||
assertTrue(result instanceof String[]);
|
||||
assertArrayEquals("Invalid result", expected, (String[]) result);
|
||||
}
|
||||
|
|
@ -178,7 +182,6 @@ public class RequestParamMethodArgumentResolverTests {
|
|||
webRequest = new ServletWebRequest(request);
|
||||
|
||||
Object result = resolver.resolveArgument(paramMultipartFile, null, webRequest, null);
|
||||
|
||||
assertTrue(result instanceof MultipartFile);
|
||||
assertEquals("Invalid result", expected, result);
|
||||
}
|
||||
|
|
@ -190,10 +193,10 @@ public class RequestParamMethodArgumentResolverTests {
|
|||
MultipartFile expected2 = new MockMultipartFile("mfilelist", "Hello World 2".getBytes());
|
||||
request.addFile(expected1);
|
||||
request.addFile(expected2);
|
||||
request.addFile(new MockMultipartFile("other", "Hello World 3".getBytes()));
|
||||
webRequest = new ServletWebRequest(request);
|
||||
|
||||
Object result = resolver.resolveArgument(paramMultipartFileList, null, webRequest, null);
|
||||
|
||||
assertTrue(result instanceof List);
|
||||
assertEquals(Arrays.asList(expected1, expected2), result);
|
||||
}
|
||||
|
|
@ -205,12 +208,13 @@ public class RequestParamMethodArgumentResolverTests {
|
|||
MultipartFile expected2 = new MockMultipartFile("mfilearray", "Hello World 2".getBytes());
|
||||
request.addFile(expected1);
|
||||
request.addFile(expected2);
|
||||
request.addFile(new MockMultipartFile("other", "Hello World 3".getBytes()));
|
||||
webRequest = new ServletWebRequest(request);
|
||||
|
||||
Object result = resolver.resolveArgument(paramMultipartFileArray, null, webRequest, null);
|
||||
|
||||
assertTrue(result instanceof MultipartFile[]);
|
||||
MultipartFile[] parts = (MultipartFile[]) result;
|
||||
assertEquals(2, parts.length);
|
||||
assertEquals(parts[0], expected1);
|
||||
assertEquals(parts[1], expected2);
|
||||
}
|
||||
|
|
@ -225,7 +229,6 @@ public class RequestParamMethodArgumentResolverTests {
|
|||
webRequest = new ServletWebRequest(request);
|
||||
|
||||
Object result = resolver.resolveArgument(paramPart, null, webRequest, null);
|
||||
|
||||
assertTrue(result instanceof Part);
|
||||
assertEquals("Invalid result", expected, result);
|
||||
}
|
||||
|
|
@ -233,16 +236,16 @@ public class RequestParamMethodArgumentResolverTests {
|
|||
@Test
|
||||
public void resolvePartList() throws Exception {
|
||||
MockHttpServletRequest request = new MockHttpServletRequest();
|
||||
MockPart expected1 = new MockPart("pfilelist", "Hello World 1".getBytes());
|
||||
MockPart expected2 = new MockPart("pfilelist", "Hello World 2".getBytes());
|
||||
request.setMethod("POST");
|
||||
request.setContentType("multipart/form-data");
|
||||
MockPart expected1 = new MockPart("pfilelist", "Hello World 1".getBytes());
|
||||
MockPart expected2 = new MockPart("pfilelist", "Hello World 2".getBytes());
|
||||
request.addPart(expected1);
|
||||
request.addPart(expected2);
|
||||
request.addPart(new MockPart("other", "Hello World 3".getBytes()));
|
||||
webRequest = new ServletWebRequest(request);
|
||||
|
||||
Object result = resolver.resolveArgument(paramPartList, null, webRequest, null);
|
||||
|
||||
assertTrue(result instanceof List);
|
||||
assertEquals(Arrays.asList(expected1, expected2), result);
|
||||
}
|
||||
|
|
@ -256,12 +259,13 @@ public class RequestParamMethodArgumentResolverTests {
|
|||
request.setContentType("multipart/form-data");
|
||||
request.addPart(expected1);
|
||||
request.addPart(expected2);
|
||||
request.addPart(new MockPart("other", "Hello World 3".getBytes()));
|
||||
webRequest = new ServletWebRequest(request);
|
||||
|
||||
Object result = resolver.resolveArgument(paramPartArray, null, webRequest, null);
|
||||
|
||||
assertTrue(result instanceof Part[]);
|
||||
Part[] parts = (Part[]) result;
|
||||
assertEquals(2, parts.length);
|
||||
assertEquals(parts[0], expected1);
|
||||
assertEquals(parts[1], expected2);
|
||||
}
|
||||
|
|
@ -274,7 +278,6 @@ public class RequestParamMethodArgumentResolverTests {
|
|||
webRequest = new ServletWebRequest(request);
|
||||
|
||||
Object result = resolver.resolveArgument(paramMultipartFileNotAnnot, null, webRequest, null);
|
||||
|
||||
assertTrue(result instanceof MultipartFile);
|
||||
assertEquals("Invalid result", expected, result);
|
||||
}
|
||||
|
|
@ -289,7 +292,6 @@ public class RequestParamMethodArgumentResolverTests {
|
|||
webRequest = new ServletWebRequest(request);
|
||||
|
||||
Object result = resolver.resolveArgument(paramMultipartFileListNotAnnot, null, webRequest, null);
|
||||
|
||||
assertTrue(result instanceof List);
|
||||
assertEquals(Arrays.asList(expected1, expected2), result);
|
||||
}
|
||||
|
|
@ -300,9 +302,7 @@ public class RequestParamMethodArgumentResolverTests {
|
|||
fail("Expected exception: request is not a multipart request");
|
||||
}
|
||||
|
||||
// SPR-9079
|
||||
|
||||
@Test
|
||||
@Test // SPR-9079
|
||||
public void isMultipartRequestHttpPut() throws Exception {
|
||||
MockMultipartHttpServletRequest request = new MockMultipartHttpServletRequest();
|
||||
MultipartFile expected = new MockMultipartFile("multipartFileList", "Hello World".getBytes());
|
||||
|
|
@ -311,17 +311,23 @@ public class RequestParamMethodArgumentResolverTests {
|
|||
webRequest = new ServletWebRequest(request);
|
||||
|
||||
Object actual = resolver.resolveArgument(paramMultipartFileListNotAnnot, null, webRequest, null);
|
||||
|
||||
assertTrue(actual instanceof List);
|
||||
assertEquals(expected, ((List<?>) actual).get(0));
|
||||
}
|
||||
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
@Test(expected = MultipartException.class)
|
||||
public void noMultipartContent() throws Exception {
|
||||
request.setMethod("POST");
|
||||
resolver.resolveArgument(paramMultipartFile, null, webRequest, null);
|
||||
fail("Expected exception: no multipart content");
|
||||
}
|
||||
|
||||
@Test(expected = MissingServletRequestPartException.class)
|
||||
public void missingMultipartFile() throws Exception {
|
||||
request.setMethod("POST");
|
||||
request.setContentType("multipart/form-data");
|
||||
resolver.resolveArgument(paramMultipartFile, null, webRequest, null);
|
||||
fail("Expected exception: request is not MultiPartHttpServletRequest but param is MultipartFile");
|
||||
fail("Expected exception: no such part found");
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
@ -334,7 +340,6 @@ public class RequestParamMethodArgumentResolverTests {
|
|||
webRequest = new ServletWebRequest(request);
|
||||
|
||||
Object result = resolver.resolveArgument(paramPartNotAnnot, null, webRequest, null);
|
||||
|
||||
assertTrue(result instanceof Part);
|
||||
assertEquals("Invalid result", expected, result);
|
||||
}
|
||||
|
|
@ -342,7 +347,6 @@ public class RequestParamMethodArgumentResolverTests {
|
|||
@Test
|
||||
public void resolveDefaultValue() throws Exception {
|
||||
Object result = resolver.resolveArgument(paramNamedDefaultValueString, null, webRequest, null);
|
||||
|
||||
assertTrue(result instanceof String);
|
||||
assertEquals("Invalid result", "bar", result);
|
||||
}
|
||||
|
|
@ -353,11 +357,8 @@ public class RequestParamMethodArgumentResolverTests {
|
|||
fail("Expected exception");
|
||||
}
|
||||
|
||||
// SPR-10578
|
||||
|
||||
@Test
|
||||
@Test // SPR-10578
|
||||
public void missingRequestParamEmptyValueConvertedToNull() throws Exception {
|
||||
|
||||
WebDataBinder binder = new WebRequestDataBinder(null);
|
||||
binder.registerCustomEditor(String.class, new StringTrimmerEditor(true));
|
||||
|
||||
|
|
@ -367,13 +368,11 @@ public class RequestParamMethodArgumentResolverTests {
|
|||
this.request.addParameter("stringNotAnnot", "");
|
||||
|
||||
Object arg = resolver.resolveArgument(paramStringNotAnnot, null, webRequest, binderFactory);
|
||||
|
||||
assertNull(arg);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void missingRequestParamEmptyValueNotRequired() throws Exception {
|
||||
|
||||
WebDataBinder binder = new WebRequestDataBinder(null);
|
||||
binder.registerCustomEditor(String.class, new StringTrimmerEditor(true));
|
||||
|
||||
|
|
@ -383,7 +382,6 @@ public class RequestParamMethodArgumentResolverTests {
|
|||
this.request.addParameter("name", "");
|
||||
|
||||
Object arg = resolver.resolveArgument(paramNotRequired, null, webRequest, binderFactory);
|
||||
|
||||
assertNull(arg);
|
||||
}
|
||||
|
||||
|
|
@ -396,17 +394,13 @@ public class RequestParamMethodArgumentResolverTests {
|
|||
assertEquals("plainValue", result);
|
||||
}
|
||||
|
||||
// SPR-8561
|
||||
|
||||
@Test
|
||||
@Test // SPR-8561
|
||||
public void resolveSimpleTypeParamToNull() throws Exception {
|
||||
Object result = resolver.resolveArgument(paramStringNotAnnot, null, webRequest, null);
|
||||
assertNull(result);
|
||||
}
|
||||
|
||||
// SPR-10180
|
||||
|
||||
@Test
|
||||
@Test // SPR-10180
|
||||
public void resolveEmptyValueToDefault() throws Exception {
|
||||
this.request.addParameter("name", "");
|
||||
Object result = resolver.resolveArgument(paramNamedDefaultValueString, null, webRequest, null);
|
||||
|
|
@ -429,13 +423,12 @@ public class RequestParamMethodArgumentResolverTests {
|
|||
|
||||
@Test
|
||||
@SuppressWarnings("rawtypes")
|
||||
public void resolveOptional() throws Exception {
|
||||
public void resolveOptionalParamValue() throws Exception {
|
||||
ConfigurableWebBindingInitializer initializer = new ConfigurableWebBindingInitializer();
|
||||
initializer.setConversionService(new DefaultConversionService());
|
||||
WebDataBinderFactory binderFactory = new DefaultDataBinderFactory(initializer);
|
||||
|
||||
Object result = resolver.resolveArgument(paramOptional, null, webRequest, binderFactory);
|
||||
assertEquals(Optional.class, result.getClass());
|
||||
assertEquals(Optional.empty(), result);
|
||||
|
||||
this.request.addParameter("name", "123");
|
||||
|
|
@ -444,8 +437,46 @@ public class RequestParamMethodArgumentResolverTests {
|
|||
assertEquals(123, ((Optional) result).get());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void resolveOptionalMultipartFile() throws Exception {
|
||||
ConfigurableWebBindingInitializer initializer = new ConfigurableWebBindingInitializer();
|
||||
initializer.setConversionService(new DefaultConversionService());
|
||||
WebDataBinderFactory binderFactory = new DefaultDataBinderFactory(initializer);
|
||||
|
||||
public void params(@RequestParam(name = "name", defaultValue = "bar") String param1,
|
||||
MockMultipartHttpServletRequest request = new MockMultipartHttpServletRequest();
|
||||
MultipartFile expected = new MockMultipartFile("mfile", "Hello World".getBytes());
|
||||
request.addFile(expected);
|
||||
webRequest = new ServletWebRequest(request);
|
||||
|
||||
Object result = resolver.resolveArgument(multipartFileOptional, null, webRequest, binderFactory);
|
||||
assertTrue(result instanceof Optional);
|
||||
assertEquals("Invalid result", expected, ((Optional<?>) result).get());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void missingOptionalMultipartFile() throws Exception {
|
||||
ConfigurableWebBindingInitializer initializer = new ConfigurableWebBindingInitializer();
|
||||
initializer.setConversionService(new DefaultConversionService());
|
||||
WebDataBinderFactory binderFactory = new DefaultDataBinderFactory(initializer);
|
||||
|
||||
request.setMethod("POST");
|
||||
request.setContentType("multipart/form-data");
|
||||
assertEquals(Optional.empty(), resolver.resolveArgument(multipartFileOptional, null, webRequest, binderFactory));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void optionalMultipartFileWithoutMultipartRequest() throws Exception {
|
||||
ConfigurableWebBindingInitializer initializer = new ConfigurableWebBindingInitializer();
|
||||
initializer.setConversionService(new DefaultConversionService());
|
||||
WebDataBinderFactory binderFactory = new DefaultDataBinderFactory(initializer);
|
||||
|
||||
assertEquals(Optional.empty(), resolver.resolveArgument(multipartFileOptional, null, webRequest, binderFactory));
|
||||
}
|
||||
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
public void handle(
|
||||
@RequestParam(name = "name", defaultValue = "bar") String param1,
|
||||
@RequestParam("name") String[] param2,
|
||||
@RequestParam("name") Map<?, ?> param3,
|
||||
@RequestParam("mfile") MultipartFile param4,
|
||||
|
|
@ -462,7 +493,8 @@ public class RequestParamMethodArgumentResolverTests {
|
|||
@RequestPart MultipartFile requestPartAnnot,
|
||||
@RequestParam("name") String paramRequired,
|
||||
@RequestParam(name = "name", required = false) String paramNotRequired,
|
||||
@RequestParam("name") Optional<Integer> paramOptional) {
|
||||
@RequestParam("name") Optional<Integer> paramOptional,
|
||||
@RequestParam("mfile") Optional<MultipartFile> multipartFileOptional) {
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2002-2015 the original author or authors.
|
||||
* Copyright 2002-2016 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.
|
||||
|
|
@ -48,12 +48,13 @@ public class MatrixVariableMethodArgumentResolver extends AbstractNamedValueMeth
|
|||
super(null);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean supportsParameter(MethodParameter parameter) {
|
||||
if (!parameter.hasParameterAnnotation(MatrixVariable.class)) {
|
||||
return false;
|
||||
}
|
||||
if (Map.class.isAssignableFrom(parameter.getParameterType())) {
|
||||
if (Map.class.isAssignableFrom(parameter.nestedIfOptional().getNestedParameterType())) {
|
||||
String variableName = parameter.getParameterAnnotation(MatrixVariable.class).name();
|
||||
return StringUtils.hasText(variableName);
|
||||
}
|
||||
|
|
@ -67,13 +68,10 @@ public class MatrixVariableMethodArgumentResolver extends AbstractNamedValueMeth
|
|||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
protected Object resolveName(String name, MethodParameter parameter, NativeWebRequest request) throws Exception {
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
Map<String, MultiValueMap<String, String>> pathParameters =
|
||||
(Map<String, MultiValueMap<String, String>>) request.getAttribute(
|
||||
HandlerMapping.MATRIX_VARIABLES_ATTRIBUTE, RequestAttributes.SCOPE_REQUEST);
|
||||
|
||||
Map<String, MultiValueMap<String, String>> pathParameters = (Map<String, MultiValueMap<String, String>>)
|
||||
request.getAttribute(HandlerMapping.MATRIX_VARIABLES_ATTRIBUTE, RequestAttributes.SCOPE_REQUEST);
|
||||
if (CollectionUtils.isEmpty(pathParameters)) {
|
||||
return null;
|
||||
}
|
||||
|
|
@ -92,10 +90,10 @@ public class MatrixVariableMethodArgumentResolver extends AbstractNamedValueMeth
|
|||
for (MultiValueMap<String, String> params : pathParameters.values()) {
|
||||
if (params.containsKey(name)) {
|
||||
if (found) {
|
||||
String paramType = parameter.getParameterType().getName();
|
||||
String paramType = parameter.getNestedParameterType().getName();
|
||||
throw new ServletRequestBindingException(
|
||||
"Found more than one match for URI path parameter '" + name +
|
||||
"' for parameter type [" + paramType + "]. Use pathVar attribute to disambiguate.");
|
||||
"' for parameter type [" + paramType + "]. Use 'pathVar' attribute to disambiguate.");
|
||||
}
|
||||
paramValues.addAll(params.get(name));
|
||||
found = true;
|
||||
|
|
@ -117,7 +115,7 @@ public class MatrixVariableMethodArgumentResolver extends AbstractNamedValueMeth
|
|||
@Override
|
||||
protected void handleMissingValue(String name, MethodParameter parameter) throws ServletRequestBindingException {
|
||||
throw new ServletRequestBindingException("Missing matrix variable '" + name +
|
||||
"' for method parameter of type " + parameter.getParameterType().getSimpleName());
|
||||
"' for method parameter of type " + parameter.getNestedParameterType().getSimpleName());
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -127,4 +125,5 @@ public class MatrixVariableMethodArgumentResolver extends AbstractNamedValueMeth
|
|||
super(annotation.name(), annotation.required(), annotation.defaultValue());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -79,7 +79,7 @@ public class PathVariableMethodArgumentResolver extends AbstractNamedValueMethod
|
|||
if (!parameter.hasParameterAnnotation(PathVariable.class)) {
|
||||
return false;
|
||||
}
|
||||
if (Map.class.isAssignableFrom(parameter.getParameterType())) {
|
||||
if (Map.class.isAssignableFrom(parameter.nestedIfOptional().getNestedParameterType())) {
|
||||
String paramName = parameter.getParameterAnnotation(PathVariable.class).value();
|
||||
return StringUtils.hasText(paramName);
|
||||
}
|
||||
|
|
@ -95,10 +95,9 @@ public class PathVariableMethodArgumentResolver extends AbstractNamedValueMethod
|
|||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
protected Object resolveName(String name, MethodParameter parameter, NativeWebRequest request) throws Exception {
|
||||
Map<String, String> uriTemplateVars =
|
||||
(Map<String, String>) request.getAttribute(
|
||||
HandlerMapping.URI_TEMPLATE_VARIABLES_ATTRIBUTE, RequestAttributes.SCOPE_REQUEST);
|
||||
return (uriTemplateVars != null) ? uriTemplateVars.get(name) : null;
|
||||
Map<String, String> uriTemplateVars = (Map<String, String>) request.getAttribute(
|
||||
HandlerMapping.URI_TEMPLATE_VARIABLES_ATTRIBUTE, RequestAttributes.SCOPE_REQUEST);
|
||||
return (uriTemplateVars != null ? uriTemplateVars.get(name) : null);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
@ -127,7 +126,7 @@ public class PathVariableMethodArgumentResolver extends AbstractNamedValueMethod
|
|||
public void contributeMethodArgument(MethodParameter parameter, Object value,
|
||||
UriComponentsBuilder builder, Map<String, Object> uriVariables, ConversionService conversionService) {
|
||||
|
||||
if (Map.class.isAssignableFrom(parameter.getParameterType())) {
|
||||
if (Map.class.isAssignableFrom(parameter.getNestedParameterType())) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2002-2015 the original author or authors.
|
||||
* Copyright 2002-2016 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.
|
||||
|
|
@ -16,20 +16,15 @@
|
|||
|
||||
package org.springframework.web.servlet.mvc.method.annotation;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.Part;
|
||||
|
||||
import org.springframework.core.GenericCollectionTypeResolver;
|
||||
import org.springframework.core.MethodParameter;
|
||||
import org.springframework.http.HttpInputMessage;
|
||||
import org.springframework.http.converter.HttpMessageConverter;
|
||||
import org.springframework.lang.UsesJava8;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.validation.BindingResult;
|
||||
import org.springframework.web.bind.MethodArgumentNotValidException;
|
||||
import org.springframework.web.bind.WebDataBinder;
|
||||
|
|
@ -41,12 +36,10 @@ import org.springframework.web.context.request.NativeWebRequest;
|
|||
import org.springframework.web.method.support.ModelAndViewContainer;
|
||||
import org.springframework.web.multipart.MultipartException;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
import org.springframework.web.multipart.MultipartHttpServletRequest;
|
||||
import org.springframework.web.multipart.MultipartResolver;
|
||||
import org.springframework.web.multipart.support.MissingServletRequestPartException;
|
||||
import org.springframework.web.multipart.support.MultipartResolutionDelegate;
|
||||
import org.springframework.web.multipart.support.RequestPartServletServerHttpRequest;
|
||||
import org.springframework.web.servlet.mvc.support.DefaultHandlerExceptionResolver;
|
||||
import org.springframework.web.util.WebUtils;
|
||||
|
||||
/**
|
||||
* Resolves the following method arguments:
|
||||
|
|
@ -65,12 +58,13 @@ import org.springframework.web.util.WebUtils;
|
|||
* it is derived from the name of the method argument.
|
||||
*
|
||||
* <p>Automatic validation may be applied if the argument is annotated with
|
||||
* {@code @javax.validation.Valid}. In case of validation failure, a
|
||||
* {@link MethodArgumentNotValidException} is raised and a 400 response status
|
||||
* code returned if {@link DefaultHandlerExceptionResolver} is configured.
|
||||
* {@code @javax.validation.Valid}. In case of validation failure, a {@link MethodArgumentNotValidException}
|
||||
* is raised and a 400 response status code returned if
|
||||
* {@link org.springframework.web.servlet.mvc.support.DefaultHandlerExceptionResolver} is configured.
|
||||
*
|
||||
* @author Rossen Stoyanchev
|
||||
* @author Brian Clozel
|
||||
* @author Juergen Hoeller
|
||||
* @since 3.1
|
||||
*/
|
||||
public class RequestPartMethodArgumentResolver extends AbstractMessageConverterMethodArgumentResolver {
|
||||
|
|
@ -107,18 +101,10 @@ public class RequestPartMethodArgumentResolver extends AbstractMessageConverterM
|
|||
return true;
|
||||
}
|
||||
else {
|
||||
if (parameter.hasParameterAnnotation(RequestParam.class)){
|
||||
return false;
|
||||
}
|
||||
else if (MultipartFile.class == parameter.getParameterType()) {
|
||||
return true;
|
||||
}
|
||||
else if ("javax.servlet.http.Part".equals(parameter.getParameterType().getName())) {
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
if (parameter.hasParameterAnnotation(RequestParam.class)) {
|
||||
return false;
|
||||
}
|
||||
return MultipartResolutionDelegate.isMultipartArgument(parameter.nestedIfOptional());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -128,87 +114,58 @@ public class RequestPartMethodArgumentResolver extends AbstractMessageConverterM
|
|||
NativeWebRequest request, WebDataBinderFactory binderFactory) throws Exception {
|
||||
|
||||
HttpServletRequest servletRequest = request.getNativeRequest(HttpServletRequest.class);
|
||||
assertIsMultipartRequest(servletRequest);
|
||||
RequestPart requestPart = parameter.getParameterAnnotation(RequestPart.class);
|
||||
boolean isRequired = ((requestPart == null || requestPart.required()) && !parameter.isOptional());
|
||||
|
||||
MultipartHttpServletRequest multipartRequest =
|
||||
WebUtils.getNativeRequest(servletRequest, MultipartHttpServletRequest.class);
|
||||
String name = getPartName(parameter, requestPart);
|
||||
parameter = parameter.nestedIfOptional();
|
||||
Object arg = null;
|
||||
|
||||
Class<?> paramType = parameter.getParameterType();
|
||||
boolean optional = paramType.getName().equals("java.util.Optional");
|
||||
if (optional) {
|
||||
parameter.increaseNestingLevel();
|
||||
paramType = parameter.getNestedParameterType();
|
||||
}
|
||||
|
||||
String partName = getPartName(parameter);
|
||||
Object arg;
|
||||
|
||||
if (MultipartFile.class == paramType) {
|
||||
Assert.notNull(multipartRequest, "Expected MultipartHttpServletRequest: is a MultipartResolver configured?");
|
||||
arg = multipartRequest.getFile(partName);
|
||||
}
|
||||
else if (isMultipartFileCollection(parameter)) {
|
||||
Assert.notNull(multipartRequest, "Expected MultipartHttpServletRequest: is a MultipartResolver configured?");
|
||||
arg = multipartRequest.getFiles(partName);
|
||||
}
|
||||
else if (isMultipartFileArray(parameter)) {
|
||||
Assert.notNull(multipartRequest, "Expected MultipartHttpServletRequest: is a MultipartResolver configured?");
|
||||
List<MultipartFile> files = multipartRequest.getFiles(partName);
|
||||
arg = files.toArray(new MultipartFile[files.size()]);
|
||||
}
|
||||
else if ("javax.servlet.http.Part".equals(paramType.getName())) {
|
||||
assertIsMultipartRequest(servletRequest);
|
||||
arg = servletRequest.getPart(partName);
|
||||
}
|
||||
else if (isPartCollection(parameter)) {
|
||||
assertIsMultipartRequest(servletRequest);
|
||||
arg = new ArrayList<Object>(servletRequest.getParts());
|
||||
}
|
||||
else if (isPartArray(parameter)) {
|
||||
assertIsMultipartRequest(servletRequest);
|
||||
arg = RequestPartResolver.resolvePart(servletRequest);
|
||||
Object mpArg = MultipartResolutionDelegate.resolveMultipartArgument(name, parameter, servletRequest);
|
||||
if (mpArg != MultipartResolutionDelegate.UNRESOLVABLE) {
|
||||
arg = mpArg;
|
||||
}
|
||||
else {
|
||||
try {
|
||||
HttpInputMessage inputMessage = new RequestPartServletServerHttpRequest(servletRequest, partName);
|
||||
HttpInputMessage inputMessage = new RequestPartServletServerHttpRequest(servletRequest, name);
|
||||
arg = readWithMessageConverters(inputMessage, parameter, parameter.getNestedGenericParameterType());
|
||||
WebDataBinder binder = binderFactory.createBinder(request, arg, partName);
|
||||
WebDataBinder binder = binderFactory.createBinder(request, arg, name);
|
||||
if (arg != null) {
|
||||
validateIfApplicable(binder, parameter);
|
||||
if (binder.getBindingResult().hasErrors() && isBindExceptionRequired(binder, parameter)) {
|
||||
throw new MethodArgumentNotValidException(parameter, binder.getBindingResult());
|
||||
}
|
||||
}
|
||||
mavContainer.addAttribute(BindingResult.MODEL_KEY_PREFIX + partName, binder.getBindingResult());
|
||||
mavContainer.addAttribute(BindingResult.MODEL_KEY_PREFIX + name, binder.getBindingResult());
|
||||
}
|
||||
catch (MissingServletRequestPartException ex) {
|
||||
// handled below
|
||||
arg = null;
|
||||
if (isRequired) {
|
||||
throw ex;
|
||||
}
|
||||
}
|
||||
catch (MultipartException ex) {
|
||||
if (isRequired) {
|
||||
throw ex;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
RequestPart requestPart = parameter.getParameterAnnotation(RequestPart.class);
|
||||
boolean isRequired = ((requestPart == null || requestPart.required()) && !optional);
|
||||
|
||||
if (arg == null && isRequired) {
|
||||
throw new MissingServletRequestPartException(partName);
|
||||
if (!MultipartResolutionDelegate.isMultipartRequest(servletRequest)) {
|
||||
throw new MultipartException("Current request is not a multipart request");
|
||||
}
|
||||
else {
|
||||
throw new MissingServletRequestPartException(name);
|
||||
}
|
||||
}
|
||||
if (optional) {
|
||||
arg = Optional.ofNullable(arg);
|
||||
if (parameter.isOptional()) {
|
||||
arg = OptionalResolver.resolveValue(arg);
|
||||
}
|
||||
|
||||
return arg;
|
||||
}
|
||||
|
||||
private static void assertIsMultipartRequest(HttpServletRequest request) {
|
||||
String contentType = request.getContentType();
|
||||
if (contentType == null || !contentType.toLowerCase().startsWith("multipart/")) {
|
||||
throw new MultipartException("The current request is not a multipart request");
|
||||
}
|
||||
}
|
||||
|
||||
private String getPartName(MethodParameter methodParam) {
|
||||
RequestPart requestPart = methodParam.getParameterAnnotation(RequestPart.class);
|
||||
private String getPartName(MethodParameter methodParam, RequestPart requestPart) {
|
||||
String partName = (requestPart != null ? requestPart.name() : "");
|
||||
if (partName.length() == 0) {
|
||||
partName = methodParam.getParameterName();
|
||||
|
|
@ -221,46 +178,18 @@ public class RequestPartMethodArgumentResolver extends AbstractMessageConverterM
|
|||
return partName;
|
||||
}
|
||||
|
||||
private boolean isMultipartFileCollection(MethodParameter methodParam) {
|
||||
Class<?> collectionType = getCollectionParameterType(methodParam);
|
||||
return MultipartFile.class == collectionType;
|
||||
}
|
||||
|
||||
private boolean isMultipartFileArray(MethodParameter methodParam) {
|
||||
Class<?> paramType = methodParam.getNestedParameterType().getComponentType();
|
||||
return MultipartFile.class == paramType;
|
||||
}
|
||||
|
||||
private boolean isPartCollection(MethodParameter methodParam) {
|
||||
Class<?> collectionType = getCollectionParameterType(methodParam);
|
||||
return (collectionType != null && "javax.servlet.http.Part".equals(collectionType.getName()));
|
||||
}
|
||||
|
||||
private boolean isPartArray(MethodParameter methodParam) {
|
||||
Class<?> paramType = methodParam.getNestedParameterType().getComponentType();
|
||||
return (paramType != null && "javax.servlet.http.Part".equals(paramType.getName()));
|
||||
}
|
||||
|
||||
private Class<?> getCollectionParameterType(MethodParameter methodParam) {
|
||||
Class<?> paramType = methodParam.getNestedParameterType();
|
||||
if (Collection.class == paramType || List.class.isAssignableFrom(paramType)){
|
||||
Class<?> valueType = GenericCollectionTypeResolver.getCollectionParameterType(methodParam);
|
||||
if (valueType != null) {
|
||||
return valueType;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Inner class to avoid hard-coded dependency on Servlet 3.0 Part type...
|
||||
* Inner class to avoid hard-coded dependency on Java 8 Optional type...
|
||||
*/
|
||||
private static class RequestPartResolver {
|
||||
private static class OptionalResolver {
|
||||
|
||||
public static Object resolvePart(HttpServletRequest servletRequest) throws Exception {
|
||||
Collection<Part> parts = servletRequest.getParts();
|
||||
return parts.toArray(new Part[parts.size()]);
|
||||
public static Object resolveValue(Object value) {
|
||||
if (value == null || (value instanceof Collection && ((Collection) value).isEmpty()) ||
|
||||
(value instanceof Object[] && ((Object[]) value).length == 0)) {
|
||||
return Optional.empty();
|
||||
}
|
||||
return Optional.of(value);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2002-2014 the original author or authors.
|
||||
* Copyright 2002-2016 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.
|
||||
|
|
@ -52,7 +52,7 @@ public class ServletCookieValueMethodArgumentResolver extends AbstractCookieValu
|
|||
protected Object resolveName(String cookieName, MethodParameter parameter, NativeWebRequest webRequest) throws Exception {
|
||||
HttpServletRequest servletRequest = webRequest.getNativeRequest(HttpServletRequest.class);
|
||||
Cookie cookieValue = WebUtils.getCookie(servletRequest, cookieName);
|
||||
if (Cookie.class.isAssignableFrom(parameter.getParameterType())) {
|
||||
if (Cookie.class.isAssignableFrom(parameter.getNestedParameterType())) {
|
||||
return cookieValue;
|
||||
}
|
||||
else if (cookieValue != null) {
|
||||
|
|
|
|||
|
|
@ -262,6 +262,12 @@ public class ServletInvocableHandlerMethod extends InvocableHandlerMethod {
|
|||
this.returnType = ResolvableType.forType(super.getGenericParameterType()).getGeneric(0);
|
||||
}
|
||||
|
||||
public ConcurrentResultMethodParameter(ConcurrentResultMethodParameter original) {
|
||||
super(original);
|
||||
this.returnValue = original.returnValue;
|
||||
this.returnType = original.returnType;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<?> getParameterType() {
|
||||
if (this.returnValue != null) {
|
||||
|
|
@ -283,6 +289,11 @@ public class ServletInvocableHandlerMethod extends InvocableHandlerMethod {
|
|||
public Type getGenericParameterType() {
|
||||
return this.returnType.getType();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ConcurrentResultMethodParameter clone() {
|
||||
return new ConcurrentResultMethodParameter(this);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2002-2015 the original author or authors.
|
||||
* Copyright 2002-2016 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.
|
||||
|
|
@ -41,6 +41,7 @@ import org.springframework.mock.web.test.MockHttpServletResponse;
|
|||
import org.springframework.mock.web.test.MockMultipartFile;
|
||||
import org.springframework.mock.web.test.MockMultipartHttpServletRequest;
|
||||
import org.springframework.mock.web.test.MockPart;
|
||||
import org.springframework.util.ReflectionUtils;
|
||||
import org.springframework.validation.beanvalidation.LocalValidatorFactoryBean;
|
||||
import org.springframework.web.bind.MethodArgumentNotValidException;
|
||||
import org.springframework.web.bind.WebDataBinder;
|
||||
|
|
@ -53,7 +54,6 @@ import org.springframework.web.method.support.ModelAndViewContainer;
|
|||
import org.springframework.web.multipart.MultipartException;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
import org.springframework.web.multipart.support.MissingServletRequestPartException;
|
||||
import org.springframework.web.multipart.support.RequestPartServletServerHttpRequest;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
import static org.mockito.BDDMockito.*;
|
||||
|
|
@ -86,7 +86,9 @@ public class RequestPartMethodArgumentResolverTests {
|
|||
private MethodParameter paramPartArray;
|
||||
private MethodParameter paramRequestParamAnnot;
|
||||
private MethodParameter optionalMultipartFile;
|
||||
private MethodParameter optionalMultipartFileList;
|
||||
private MethodParameter optionalPart;
|
||||
private MethodParameter optionalPartList;
|
||||
private MethodParameter optionalRequestPart;
|
||||
|
||||
private NativeWebRequest webRequest;
|
||||
|
|
@ -97,10 +99,7 @@ public class RequestPartMethodArgumentResolverTests {
|
|||
@SuppressWarnings("unchecked")
|
||||
@Before
|
||||
public void setUp() throws Exception {
|
||||
Method method = getClass().getMethod("handle", SimpleBean.class, SimpleBean.class,
|
||||
SimpleBean.class, MultipartFile.class, List.class, MultipartFile[].class,
|
||||
Integer.TYPE, MultipartFile.class, Part.class, List.class, Part[].class,
|
||||
MultipartFile.class, Optional.class, Optional.class, Optional.class);
|
||||
Method method = ReflectionUtils.findMethod(getClass(), "handle", (Class<?>[]) null);
|
||||
|
||||
paramRequestPart = new SynthesizingMethodParameter(method, 0);
|
||||
paramRequestPart.initParameterNameDiscovery(new LocalVariableTableParameterNameDiscoverer());
|
||||
|
|
@ -119,9 +118,13 @@ public class RequestPartMethodArgumentResolverTests {
|
|||
paramRequestParamAnnot = new SynthesizingMethodParameter(method, 11);
|
||||
optionalMultipartFile = new SynthesizingMethodParameter(method, 12);
|
||||
optionalMultipartFile.initParameterNameDiscovery(new LocalVariableTableParameterNameDiscoverer());
|
||||
optionalPart = new SynthesizingMethodParameter(method, 13);
|
||||
optionalMultipartFileList = new SynthesizingMethodParameter(method, 13);
|
||||
optionalMultipartFileList.initParameterNameDiscovery(new LocalVariableTableParameterNameDiscoverer());
|
||||
optionalPart = new SynthesizingMethodParameter(method, 14);
|
||||
optionalPart.initParameterNameDiscovery(new LocalVariableTableParameterNameDiscoverer());
|
||||
optionalRequestPart = new SynthesizingMethodParameter(method, 14);
|
||||
optionalPartList = new SynthesizingMethodParameter(method, 15);
|
||||
optionalPartList.initParameterNameDiscovery(new LocalVariableTableParameterNameDiscoverer());
|
||||
optionalRequestPart = new SynthesizingMethodParameter(method, 16);
|
||||
|
||||
messageConverter = mock(HttpMessageConverter.class);
|
||||
given(messageConverter.getSupportedMediaTypes()).willReturn(Collections.singletonList(MediaType.TEXT_PLAIN));
|
||||
|
|
@ -136,35 +139,41 @@ public class RequestPartMethodArgumentResolverTests {
|
|||
multipartRequest = new MockMultipartHttpServletRequest();
|
||||
multipartRequest.addFile(multipartFile1);
|
||||
multipartRequest.addFile(multipartFile2);
|
||||
multipartRequest.addFile(new MockMultipartFile("otherPart", "", "text/plain", content));
|
||||
webRequest = new ServletWebRequest(multipartRequest, new MockHttpServletResponse());
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void supportsParameter() {
|
||||
assertTrue("RequestPart parameter not supported", resolver.supportsParameter(paramRequestPart));
|
||||
assertTrue("MultipartFile parameter not supported", resolver.supportsParameter(paramMultipartFileNotAnnot));
|
||||
assertTrue("Part parameter not supported", resolver.supportsParameter(paramPart));
|
||||
assertTrue("List<Part> parameter not supported", resolver.supportsParameter(paramPartList));
|
||||
assertTrue("Part[] parameter not supported", resolver.supportsParameter(paramPartArray));
|
||||
assertTrue("MultipartFile parameter not supported", resolver.supportsParameter(paramMultipartFile));
|
||||
assertTrue("List<MultipartFile> parameter not supported", resolver.supportsParameter(paramMultipartFileList));
|
||||
assertTrue("MultipartFile[] parameter not supported", resolver.supportsParameter(paramMultipartFileArray));
|
||||
assertFalse("non-RequestPart parameter should not be supported", resolver.supportsParameter(paramInt));
|
||||
assertFalse("@RequestParam args should not be supported", resolver.supportsParameter(paramRequestParamAnnot));
|
||||
assertTrue(resolver.supportsParameter(paramRequestPart));
|
||||
assertTrue(resolver.supportsParameter(paramNamedRequestPart));
|
||||
assertTrue(resolver.supportsParameter(paramValidRequestPart));
|
||||
assertTrue(resolver.supportsParameter(paramMultipartFile));
|
||||
assertTrue(resolver.supportsParameter(paramMultipartFileList));
|
||||
assertTrue(resolver.supportsParameter(paramMultipartFileArray));
|
||||
assertFalse(resolver.supportsParameter(paramInt));
|
||||
assertTrue(resolver.supportsParameter(paramMultipartFileNotAnnot));
|
||||
assertTrue(resolver.supportsParameter(paramPart));
|
||||
assertTrue(resolver.supportsParameter(paramPartList));
|
||||
assertTrue(resolver.supportsParameter(paramPartArray));
|
||||
assertFalse(resolver.supportsParameter(paramRequestParamAnnot));
|
||||
assertTrue(resolver.supportsParameter(optionalMultipartFile));
|
||||
assertTrue(resolver.supportsParameter(optionalMultipartFileList));
|
||||
assertTrue(resolver.supportsParameter(optionalPart));
|
||||
assertTrue(resolver.supportsParameter(optionalPartList));
|
||||
assertTrue(resolver.supportsParameter(optionalRequestPart));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void resolveMultipartFile() throws Exception {
|
||||
Object actual = resolver.resolveArgument(paramMultipartFile, null, webRequest, null);
|
||||
assertNotNull(actual);
|
||||
assertSame(multipartFile1, actual);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void resolveMultipartFileList() throws Exception {
|
||||
Object actual = resolver.resolveArgument(paramMultipartFileList, null, webRequest, null);
|
||||
assertNotNull(actual);
|
||||
assertTrue(actual instanceof List);
|
||||
assertEquals(Arrays.asList(multipartFile1, multipartFile2), actual);
|
||||
}
|
||||
|
|
@ -175,6 +184,7 @@ public class RequestPartMethodArgumentResolverTests {
|
|||
assertNotNull(actual);
|
||||
assertTrue(actual instanceof MultipartFile[]);
|
||||
MultipartFile[] parts = (MultipartFile[]) actual;
|
||||
assertEquals(2, parts.length);
|
||||
assertEquals(parts[0], multipartFile1);
|
||||
assertEquals(parts[1], multipartFile2);
|
||||
}
|
||||
|
|
@ -184,6 +194,7 @@ public class RequestPartMethodArgumentResolverTests {
|
|||
MockMultipartHttpServletRequest request = new MockMultipartHttpServletRequest();
|
||||
MultipartFile expected = new MockMultipartFile("multipartFileNotAnnot", "Hello World".getBytes());
|
||||
request.addFile(expected);
|
||||
request.addFile(new MockMultipartFile("otherPart", "", "text/plain", "Hello World".getBytes()));
|
||||
webRequest = new ServletWebRequest(request);
|
||||
|
||||
Object result = resolver.resolveArgument(paramMultipartFileNotAnnot, null, webRequest, null);
|
||||
|
|
@ -194,52 +205,52 @@ public class RequestPartMethodArgumentResolverTests {
|
|||
|
||||
@Test
|
||||
public void resolvePartArgument() throws Exception {
|
||||
MockPart expected = new MockPart("part", "Hello World".getBytes());
|
||||
MockHttpServletRequest request = new MockHttpServletRequest();
|
||||
request.setMethod("POST");
|
||||
request.setContentType("multipart/form-data");
|
||||
MockPart expected = new MockPart("part", "Hello World".getBytes());
|
||||
request.addPart(expected);
|
||||
request.addPart(new MockPart("otherPart", "Hello World".getBytes()));
|
||||
webRequest = new ServletWebRequest(request);
|
||||
|
||||
Object result = resolver.resolveArgument(paramPart, null, webRequest, null);
|
||||
|
||||
assertTrue(result instanceof Part);
|
||||
assertEquals("Invalid result", expected, result);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void resolvePartListArgument() throws Exception {
|
||||
MockPart part1 = new MockPart("requestPart1", "Hello World 1".getBytes());
|
||||
MockPart part2 = new MockPart("requestPart2", "Hello World 2".getBytes());
|
||||
MockHttpServletRequest request = new MockHttpServletRequest();
|
||||
request.setMethod("POST");
|
||||
request.setContentType("multipart/form-data");
|
||||
MockPart part1 = new MockPart("requestPart", "Hello World 1".getBytes());
|
||||
MockPart part2 = new MockPart("requestPart", "Hello World 2".getBytes());
|
||||
request.addPart(part1);
|
||||
request.addPart(part2);
|
||||
request.addPart(new MockPart("otherPart", "Hello World".getBytes()));
|
||||
webRequest = new ServletWebRequest(request);
|
||||
|
||||
Object result = resolver.resolveArgument(paramPartList, null, webRequest, null);
|
||||
|
||||
assertTrue(result instanceof List);
|
||||
assertEquals(Arrays.asList(part1, part2), result);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void resolvePartArrayArgument() throws Exception {
|
||||
MockPart part1 = new MockPart("requestPart1", "Hello World 1".getBytes());
|
||||
MockPart part2 = new MockPart("requestPart2", "Hello World 2".getBytes());
|
||||
MockHttpServletRequest request = new MockHttpServletRequest();
|
||||
request.setMethod("POST");
|
||||
request.setContentType("multipart/form-data");
|
||||
MockPart part1 = new MockPart("requestPart", "Hello World 1".getBytes());
|
||||
MockPart part2 = new MockPart("requestPart", "Hello World 2".getBytes());
|
||||
request.addPart(part1);
|
||||
request.addPart(part2);
|
||||
request.addPart(new MockPart("otherPart", "Hello World".getBytes()));
|
||||
webRequest = new ServletWebRequest(request);
|
||||
|
||||
Object result = resolver.resolveArgument(paramPartArray, null, webRequest, null);
|
||||
|
||||
assertTrue(result instanceof Part[]);
|
||||
Part[] parts = (Part[]) result;
|
||||
assertThat(parts, Matchers.arrayWithSize(2));
|
||||
assertEquals(2, parts.length);
|
||||
assertEquals(parts[0], part1);
|
||||
assertEquals(parts[1], part2);
|
||||
}
|
||||
|
|
@ -302,8 +313,8 @@ public class RequestPartMethodArgumentResolverTests {
|
|||
@Test // SPR-9079
|
||||
public void isMultipartRequestPut() throws Exception {
|
||||
this.multipartRequest.setMethod("PUT");
|
||||
Object actual = resolver.resolveArgument(paramMultipartFile, null, webRequest, null);
|
||||
assertSame(multipartFile1, actual);
|
||||
Object actualValue = resolver.resolveArgument(paramMultipartFile, null, webRequest, null);
|
||||
assertSame(multipartFile1, actualValue);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
@ -311,12 +322,16 @@ public class RequestPartMethodArgumentResolverTests {
|
|||
MockMultipartHttpServletRequest request = new MockMultipartHttpServletRequest();
|
||||
MultipartFile expected = new MockMultipartFile("optionalMultipartFile", "Hello World".getBytes());
|
||||
request.addFile(expected);
|
||||
request.addFile(new MockMultipartFile("otherPart", "", "text/plain", "Hello World".getBytes()));
|
||||
webRequest = new ServletWebRequest(request);
|
||||
|
||||
Object result = resolver.resolveArgument(optionalMultipartFile, null, webRequest, null);
|
||||
Object actualValue = resolver.resolveArgument(optionalMultipartFile, null, webRequest, null);
|
||||
assertTrue(actualValue instanceof Optional);
|
||||
assertEquals("Invalid result", expected, ((Optional) actualValue).get());
|
||||
|
||||
assertTrue(result instanceof Optional);
|
||||
assertEquals("Invalid result", expected, ((Optional) result).get());
|
||||
actualValue = resolver.resolveArgument(optionalMultipartFile, null, webRequest, null);
|
||||
assertTrue(actualValue instanceof Optional);
|
||||
assertEquals("Invalid result", expected, ((Optional) actualValue).get());
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
@ -324,10 +339,62 @@ public class RequestPartMethodArgumentResolverTests {
|
|||
MockMultipartHttpServletRequest request = new MockMultipartHttpServletRequest();
|
||||
webRequest = new ServletWebRequest(request);
|
||||
|
||||
Object result = resolver.resolveArgument(optionalMultipartFile, null, webRequest, null);
|
||||
Object actualValue = resolver.resolveArgument(optionalMultipartFile, null, webRequest, null);
|
||||
assertEquals("Invalid argument value", Optional.empty(), actualValue);
|
||||
|
||||
assertTrue(result instanceof Optional);
|
||||
assertFalse("Invalid result", ((Optional) result).isPresent());
|
||||
actualValue = resolver.resolveArgument(optionalMultipartFile, null, webRequest, null);
|
||||
assertEquals("Invalid argument value", Optional.empty(), actualValue);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void resolveOptionalMultipartFileArgumentWithoutMultipartRequest() throws Exception {
|
||||
webRequest = new ServletWebRequest(new MockHttpServletRequest());
|
||||
|
||||
Object actualValue = resolver.resolveArgument(optionalMultipartFile, null, webRequest, null);
|
||||
assertEquals("Invalid argument value", Optional.empty(), actualValue);
|
||||
|
||||
actualValue = resolver.resolveArgument(optionalMultipartFile, null, webRequest, null);
|
||||
assertEquals("Invalid argument value", Optional.empty(), actualValue);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void resolveOptionalMultipartFileList() throws Exception {
|
||||
MockMultipartHttpServletRequest request = new MockMultipartHttpServletRequest();
|
||||
MultipartFile expected = new MockMultipartFile("requestPart", "Hello World".getBytes());
|
||||
request.addFile(expected);
|
||||
request.addFile(new MockMultipartFile("otherPart", "", "text/plain", "Hello World".getBytes()));
|
||||
webRequest = new ServletWebRequest(request);
|
||||
|
||||
Object actualValue = resolver.resolveArgument(optionalMultipartFileList, null, webRequest, null);
|
||||
assertTrue(actualValue instanceof Optional);
|
||||
assertEquals("Invalid result", Collections.singletonList(expected), ((Optional) actualValue).get());
|
||||
|
||||
actualValue = resolver.resolveArgument(optionalMultipartFileList, null, webRequest, null);
|
||||
assertTrue(actualValue instanceof Optional);
|
||||
assertEquals("Invalid result", Collections.singletonList(expected), ((Optional) actualValue).get());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void resolveOptionalMultipartFileListNotPresent() throws Exception {
|
||||
MockMultipartHttpServletRequest request = new MockMultipartHttpServletRequest();
|
||||
webRequest = new ServletWebRequest(request);
|
||||
|
||||
Object actualValue = resolver.resolveArgument(optionalMultipartFileList, null, webRequest, null);
|
||||
assertEquals("Invalid argument value", Optional.empty(), actualValue);
|
||||
|
||||
actualValue = resolver.resolveArgument(optionalMultipartFileList, null, webRequest, null);
|
||||
assertEquals("Invalid argument value", Optional.empty(), actualValue);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void resolveOptionalMultipartFileListWithoutMultipartRequest() throws Exception {
|
||||
webRequest = new ServletWebRequest(new MockHttpServletRequest());
|
||||
|
||||
Object actualValue = resolver.resolveArgument(optionalMultipartFileList, null, webRequest, null);
|
||||
assertEquals("Invalid argument value", Optional.empty(), actualValue);
|
||||
|
||||
actualValue = resolver.resolveArgument(optionalMultipartFileList, null, webRequest, null);
|
||||
assertEquals("Invalid argument value", Optional.empty(), actualValue);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
@ -337,12 +404,16 @@ public class RequestPartMethodArgumentResolverTests {
|
|||
request.setMethod("POST");
|
||||
request.setContentType("multipart/form-data");
|
||||
request.addPart(expected);
|
||||
request.addPart(new MockPart("otherPart", "Hello World".getBytes()));
|
||||
webRequest = new ServletWebRequest(request);
|
||||
|
||||
Object result = resolver.resolveArgument(optionalPart, null, webRequest, null);
|
||||
Object actualValue = resolver.resolveArgument(optionalPart, null, webRequest, null);
|
||||
assertTrue(actualValue instanceof Optional);
|
||||
assertEquals("Invalid result", expected, ((Optional) actualValue).get());
|
||||
|
||||
assertTrue(result instanceof Optional);
|
||||
assertEquals("Invalid result", expected, ((Optional) result).get());
|
||||
actualValue = resolver.resolveArgument(optionalPart, null, webRequest, null);
|
||||
assertTrue(actualValue instanceof Optional);
|
||||
assertEquals("Invalid result", expected, ((Optional) actualValue).get());
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
@ -352,36 +423,108 @@ public class RequestPartMethodArgumentResolverTests {
|
|||
request.setContentType("multipart/form-data");
|
||||
webRequest = new ServletWebRequest(request);
|
||||
|
||||
Object result = resolver.resolveArgument(optionalPart, null, webRequest, null);
|
||||
Object actualValue = resolver.resolveArgument(optionalPart, null, webRequest, null);
|
||||
assertEquals("Invalid argument value", Optional.empty(), actualValue);
|
||||
|
||||
assertTrue(result instanceof Optional);
|
||||
assertFalse("Invalid result", ((Optional) result).isPresent());
|
||||
actualValue = resolver.resolveArgument(optionalPart, null, webRequest, null);
|
||||
assertEquals("Invalid argument value", Optional.empty(), actualValue);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void resolveOptionalPartArgumentWithoutMultipartRequest() throws Exception {
|
||||
webRequest = new ServletWebRequest(new MockHttpServletRequest());
|
||||
|
||||
Object actualValue = resolver.resolveArgument(optionalPart, null, webRequest, null);
|
||||
assertEquals("Invalid argument value", Optional.empty(), actualValue);
|
||||
|
||||
actualValue = resolver.resolveArgument(optionalPart, null, webRequest, null);
|
||||
assertEquals("Invalid argument value", Optional.empty(), actualValue);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void resolveOptionalPartList() throws Exception {
|
||||
MockPart expected = new MockPart("requestPart", "Hello World".getBytes());
|
||||
MockHttpServletRequest request = new MockHttpServletRequest();
|
||||
request.setMethod("POST");
|
||||
request.setContentType("multipart/form-data");
|
||||
request.addPart(expected);
|
||||
request.addPart(new MockPart("otherPart", "Hello World".getBytes()));
|
||||
webRequest = new ServletWebRequest(request);
|
||||
|
||||
Object actualValue = resolver.resolveArgument(optionalPartList, null, webRequest, null);
|
||||
assertTrue(actualValue instanceof Optional);
|
||||
assertEquals("Invalid result", Collections.singletonList(expected), ((Optional) actualValue).get());
|
||||
|
||||
actualValue = resolver.resolveArgument(optionalPartList, null, webRequest, null);
|
||||
assertTrue(actualValue instanceof Optional);
|
||||
assertEquals("Invalid result", Collections.singletonList(expected), ((Optional) actualValue).get());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void resolveOptionalPartListNotPresent() throws Exception {
|
||||
MockHttpServletRequest request = new MockHttpServletRequest();
|
||||
request.setMethod("POST");
|
||||
request.setContentType("multipart/form-data");
|
||||
webRequest = new ServletWebRequest(request);
|
||||
|
||||
Object actualValue = resolver.resolveArgument(optionalPartList, null, webRequest, null);
|
||||
assertEquals("Invalid argument value", Optional.empty(), actualValue);
|
||||
|
||||
actualValue = resolver.resolveArgument(optionalPartList, null, webRequest, null);
|
||||
assertEquals("Invalid argument value", Optional.empty(), actualValue);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void resolveOptionalPartListWithoutMultipartRequest() throws Exception {
|
||||
webRequest = new ServletWebRequest(new MockHttpServletRequest());
|
||||
|
||||
Object actualValue = resolver.resolveArgument(optionalPartList, null, webRequest, null);
|
||||
assertEquals("Invalid argument value", Optional.empty(), actualValue);
|
||||
|
||||
actualValue = resolver.resolveArgument(optionalPartList, null, webRequest, null);
|
||||
assertEquals("Invalid argument value", Optional.empty(), actualValue);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void resolveOptionalRequestPart() throws Exception {
|
||||
SimpleBean simpleBean = new SimpleBean("foo");
|
||||
|
||||
given(messageConverter.canRead(SimpleBean.class, MediaType.TEXT_PLAIN)).willReturn(true);
|
||||
given(messageConverter.read(eq(SimpleBean.class), isA(HttpInputMessage.class))).willReturn(simpleBean);
|
||||
|
||||
ModelAndViewContainer mavContainer = new ModelAndViewContainer();
|
||||
Object actualValue = resolver.resolveArgument(optionalRequestPart, mavContainer, webRequest, new ValidatingBinderFactory());
|
||||
|
||||
Object actualValue = resolver.resolveArgument(optionalRequestPart, mavContainer, webRequest, new ValidatingBinderFactory());
|
||||
assertEquals("Invalid argument value", Optional.of(simpleBean), actualValue);
|
||||
assertFalse("The requestHandled flag shouldn't change", mavContainer.isRequestHandled());
|
||||
|
||||
actualValue = resolver.resolveArgument(optionalRequestPart, mavContainer, webRequest, new ValidatingBinderFactory());
|
||||
assertEquals("Invalid argument value", Optional.of(simpleBean), actualValue);
|
||||
assertFalse("The requestHandled flag shouldn't change", mavContainer.isRequestHandled());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void resolveOptionalRequestPartNotPresent() throws Exception {
|
||||
given(messageConverter.canRead(SimpleBean.class, MediaType.TEXT_PLAIN)).willReturn(true);
|
||||
given(messageConverter.read(eq(SimpleBean.class), isA(RequestPartServletServerHttpRequest.class))).willReturn(null);
|
||||
|
||||
ModelAndViewContainer mavContainer = new ModelAndViewContainer();
|
||||
Object actualValue = resolver.resolveArgument(optionalRequestPart, mavContainer, webRequest, new ValidatingBinderFactory());
|
||||
MockHttpServletRequest request = new MockHttpServletRequest();
|
||||
request.setMethod("POST");
|
||||
request.setContentType("multipart/form-data");
|
||||
webRequest = new ServletWebRequest(request);
|
||||
|
||||
Object actualValue = resolver.resolveArgument(optionalRequestPart, null, webRequest, null);
|
||||
assertEquals("Invalid argument value", Optional.empty(), actualValue);
|
||||
|
||||
actualValue = resolver.resolveArgument(optionalRequestPart, null, webRequest, null);
|
||||
assertEquals("Invalid argument value", Optional.empty(), actualValue);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void resolveOptionalRequestPartWithoutMultipartRequest() throws Exception {
|
||||
webRequest = new ServletWebRequest(new MockHttpServletRequest());
|
||||
|
||||
Object actualValue = resolver.resolveArgument(optionalRequestPart, null, webRequest, null);
|
||||
assertEquals("Invalid argument value", Optional.empty(), actualValue);
|
||||
|
||||
actualValue = resolver.resolveArgument(optionalRequestPart, null, webRequest, null);
|
||||
assertEquals("Invalid argument value", Optional.empty(), actualValue);
|
||||
assertFalse("The requestHandled flag shouldn't change", mavContainer.isRequestHandled());
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -390,8 +533,8 @@ public class RequestPartMethodArgumentResolverTests {
|
|||
given(messageConverter.read(eq(SimpleBean.class), isA(HttpInputMessage.class))).willReturn(argValue);
|
||||
|
||||
ModelAndViewContainer mavContainer = new ModelAndViewContainer();
|
||||
Object actualValue = resolver.resolveArgument(parameter, mavContainer, webRequest, new ValidatingBinderFactory());
|
||||
|
||||
Object actualValue = resolver.resolveArgument(parameter, mavContainer, webRequest, new ValidatingBinderFactory());
|
||||
assertEquals("Invalid argument value", argValue, actualValue);
|
||||
assertFalse("The requestHandled flag shouldn't change", mavContainer.isRequestHandled());
|
||||
}
|
||||
|
|
@ -425,22 +568,26 @@ public class RequestPartMethodArgumentResolverTests {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
public void handle(@RequestPart SimpleBean requestPart,
|
||||
@RequestPart(value="requestPart", required=false) SimpleBean namedRequestPart,
|
||||
@Valid @RequestPart("requestPart") SimpleBean validRequestPart,
|
||||
@RequestPart("requestPart") MultipartFile multipartFile,
|
||||
@RequestPart("requestPart") List<MultipartFile> multipartFileList,
|
||||
@RequestPart("requestPart") MultipartFile[] multipartFileArray,
|
||||
int i,
|
||||
MultipartFile multipartFileNotAnnot,
|
||||
Part part,
|
||||
@RequestPart("part") List<Part> partList,
|
||||
@RequestPart("part") Part[] partArray,
|
||||
@RequestParam MultipartFile requestParamAnnot,
|
||||
Optional<MultipartFile> optionalMultipartFile,
|
||||
Optional<Part> optionalPart,
|
||||
@RequestPart("requestPart") Optional<SimpleBean> optionalRequestPart) {
|
||||
public void handle(
|
||||
@RequestPart SimpleBean requestPart,
|
||||
@RequestPart(value="requestPart", required=false) SimpleBean namedRequestPart,
|
||||
@Valid @RequestPart("requestPart") SimpleBean validRequestPart,
|
||||
@RequestPart("requestPart") MultipartFile multipartFile,
|
||||
@RequestPart("requestPart") List<MultipartFile> multipartFileList,
|
||||
@RequestPart("requestPart") MultipartFile[] multipartFileArray,
|
||||
int i,
|
||||
MultipartFile multipartFileNotAnnot,
|
||||
Part part,
|
||||
@RequestPart("requestPart") List<Part> partList,
|
||||
@RequestPart("requestPart") Part[] partArray,
|
||||
@RequestParam MultipartFile requestParamAnnot,
|
||||
Optional<MultipartFile> optionalMultipartFile,
|
||||
@RequestPart("requestPart") Optional<List<MultipartFile>> optionalMultipartFileList,
|
||||
Optional<Part> optionalPart,
|
||||
@RequestPart("requestPart") Optional<List<Part>> optionalPartList,
|
||||
@RequestPart("requestPart") Optional<SimpleBean> optionalRequestPart) {
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2002-2013 the original author or authors.
|
||||
* Copyright 2002-2016 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.
|
||||
|
|
@ -47,7 +47,9 @@ import org.springframework.web.servlet.mvc.multiaction.NoSuchRequestHandlingMeth
|
|||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
/** @author Arjen Poutsma */
|
||||
/**
|
||||
* @author Arjen Poutsma
|
||||
*/
|
||||
public class DefaultHandlerExceptionResolverTests {
|
||||
|
||||
private DefaultHandlerExceptionResolver exceptionResolver;
|
||||
|
|
@ -174,7 +176,9 @@ public class DefaultHandlerExceptionResolverTests {
|
|||
assertNotNull("No ModelAndView returned", mav);
|
||||
assertTrue("No Empty ModelAndView returned", mav.isEmpty());
|
||||
assertEquals("Invalid status code", 400, response.getStatus());
|
||||
assertEquals("Required request part 'name' is not present.", response.getErrorMessage());
|
||||
assertTrue(response.getErrorMessage().contains("request part"));
|
||||
assertTrue(response.getErrorMessage().contains("name"));
|
||||
assertTrue(response.getErrorMessage().contains("not present"));
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
@ -211,6 +215,7 @@ public class DefaultHandlerExceptionResolverTests {
|
|||
assertSame(ex, request.getAttribute("javax.servlet.error.exception"));
|
||||
}
|
||||
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
public void handle(String arg) {
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue