Support Part/MultiPartFile arrays in ArgumentResolvers

Prior to this commit, parts of a multipart HTTP request could be
injected in @RequestPart and @RequestParam annotated arguments, when
using types:
* MultipartFile, Collection<MultiPartFile>
* javax.servlet.Part, Collection<Part>

This commits updates @RequestParam and @RequestPart argument resolvers
and now allows the array versions of those types:
* Part[]
* MultiPartFile[]

Note that the MockHtpServletRequest backing tests for standard
Servlets implementations now uses a MultiValueMap to store parts
(versus a simple hashmap).

Issue: SPR-11353
This commit is contained in:
Brian Clozel
2014-01-27 14:56:44 +01:00
parent 78542777d6
commit cc0a845653
5 changed files with 258 additions and 50 deletions

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2013 the original author or authors.
* Copyright 2002-2014 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.
@@ -23,6 +23,7 @@ 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;
@@ -69,6 +70,7 @@ import org.springframework.web.util.WebUtils;
*
* @author Arjen Poutsma
* @author Rossen Stoyanchev
* @author Brian Clozel
* @since 3.1
* @see RequestParamMapMethodArgumentResolver
*/
@@ -174,6 +176,11 @@ public class RequestParamMethodArgumentResolver extends AbstractNamedValueMethod
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?");
arg = multipartRequest.getFiles(name).toArray(new MultipartFile[0]);
}
else if ("javax.servlet.http.Part".equals(parameter.getParameterType().getName())) {
assertIsMultipartRequest(servletRequest);
arg = servletRequest.getPart(name);
@@ -182,6 +189,10 @@ public class RequestParamMethodArgumentResolver extends AbstractNamedValueMethod
assertIsMultipartRequest(servletRequest);
arg = new ArrayList<Object>(servletRequest.getParts());
}
else if (isPartArray(parameter)) {
assertIsMultipartRequest(servletRequest);
arg = RequestPartResolver.resolvePart(servletRequest);
}
else {
arg = null;
if (multipartRequest != null) {
@@ -218,6 +229,16 @@ public class RequestParamMethodArgumentResolver extends AbstractNamedValueMethod
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 boolean isMultipartFileArray(MethodParameter parameter) {
Class<?> paramType = parameter.getParameterType().getComponentType();
return ((paramType != null) && MultipartFile.class.equals(paramType));
}
private Class<?> getCollectionParameterType(MethodParameter parameter) {
Class<?> paramType = parameter.getParameterType();
if (Collection.class.equals(paramType) || List.class.isAssignableFrom(paramType)){
@@ -277,4 +298,11 @@ 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()]);
}
}
}