1616
1717package org .springframework .web .method .annotation ;
1818
19+ import java .util .Collection ;
1920import java .util .LinkedHashMap ;
2021import java .util .Map ;
22+ import javax .servlet .http .HttpServletRequest ;
23+ import javax .servlet .http .Part ;
2124
2225import org .springframework .core .MethodParameter ;
26+ import org .springframework .core .ResolvableType ;
2327import org .springframework .lang .Nullable ;
2428import org .springframework .util .LinkedMultiValueMap ;
2529import org .springframework .util .MultiValueMap ;
2933import org .springframework .web .context .request .NativeWebRequest ;
3034import org .springframework .web .method .support .HandlerMethodArgumentResolver ;
3135import org .springframework .web .method .support .ModelAndViewContainer ;
36+ import org .springframework .web .multipart .MultipartFile ;
37+ import org .springframework .web .multipart .MultipartRequest ;
38+ import org .springframework .web .multipart .support .MultipartResolutionDelegate ;
3239
3340/**
3441 * Resolves {@link Map} method arguments annotated with an @{@link RequestParam}
3542 * where the annotation does not specify a request parameter name.
36- * See {@link RequestParamMethodArgumentResolver} for resolving {@link Map}
37- * method arguments with a request parameter name.
3843 *
39- * <p>The created {@link Map} contains all request parameter name/value pairs.
40- * If the method parameter type is {@link MultiValueMap} instead, the created
41- * map contains all request parameters and all there values for cases where
42- * request parameters have multiple values.
44+ * <p>The created {@link Map} contains all request parameter name/value pairs,
45+ * or all multipart files for a given parameter name if specifically declared
46+ * with {@link MultipartFile} as the value type. If the method parameter type is
47+ * {@link MultiValueMap} instead, the created map contains all request parameters
48+ * and all their values for cases where request parameters have multiple values
49+ * (or multiple multipart files of the same name).
4350 *
4451 * @author Arjen Poutsma
4552 * @author Rossen Stoyanchev
53+ * @author Juergen Hoeller
4654 * @since 3.1
4755 * @see RequestParamMethodArgumentResolver
56+ * @see HttpServletRequest#getParameterMap()
57+ * @see MultipartRequest#getMultiFileMap()
58+ * @see MultipartRequest#getFileMap()
4859 */
4960public class RequestParamMapMethodArgumentResolver implements HandlerMethodArgumentResolver {
5061
@@ -59,26 +70,71 @@ public boolean supportsParameter(MethodParameter parameter) {
5970 public Object resolveArgument (MethodParameter parameter , @ Nullable ModelAndViewContainer mavContainer ,
6071 NativeWebRequest webRequest , @ Nullable WebDataBinderFactory binderFactory ) throws Exception {
6172
62- Class <?> paramType = parameter . getParameterType ( );
73+ ResolvableType resolvableType = ResolvableType . forMethodParameter ( parameter );
6374
64- Map <String , String []> parameterMap = webRequest .getParameterMap ();
65- if (MultiValueMap .class .isAssignableFrom (paramType )) {
66- MultiValueMap <String , String > result = new LinkedMultiValueMap <>(parameterMap .size ());
67- parameterMap .forEach ((key , values ) -> {
68- for (String value : values ) {
69- result .add (key , value );
75+ if (MultiValueMap .class .isAssignableFrom (parameter .getParameterType ())) {
76+ // MultiValueMap
77+ Class <?> valueType = resolvableType .as (MultiValueMap .class ).getGeneric (1 ).resolve ();
78+ if (valueType == MultipartFile .class ) {
79+ MultipartRequest multipartRequest = MultipartResolutionDelegate .resolveMultipartRequest (webRequest );
80+ return (multipartRequest != null ? multipartRequest .getMultiFileMap () : new LinkedMultiValueMap <>(0 ));
81+ }
82+ else if (valueType == Part .class ) {
83+ HttpServletRequest servletRequest = webRequest .getNativeRequest (HttpServletRequest .class );
84+ if (servletRequest != null && MultipartResolutionDelegate .isMultipartRequest (servletRequest )) {
85+ Collection <Part > parts = servletRequest .getParts ();
86+ LinkedMultiValueMap <String , Part > result = new LinkedMultiValueMap <>(parts .size ());
87+ for (Part part : parts ) {
88+ result .add (part .getName (), part );
89+ }
90+ return result ;
7091 }
71- });
72- return result ;
92+ return new LinkedMultiValueMap <>(0 );
93+ }
94+ else {
95+ Map <String , String []> parameterMap = webRequest .getParameterMap ();
96+ MultiValueMap <String , String > result = new LinkedMultiValueMap <>(parameterMap .size ());
97+ parameterMap .forEach ((key , values ) -> {
98+ for (String value : values ) {
99+ result .add (key , value );
100+ }
101+ });
102+ return result ;
103+ }
73104 }
105+
74106 else {
75- Map <String , String > result = new LinkedHashMap <>(parameterMap .size ());
76- parameterMap .forEach ((key , values ) -> {
77- if (values .length > 0 ) {
78- result .put (key , values [0 ]);
107+ // Regular Map
108+ Class <?> valueType = resolvableType .asMap ().getGeneric (1 ).resolve ();
109+ if (valueType == MultipartFile .class ) {
110+ MultipartRequest multipartRequest = MultipartResolutionDelegate .resolveMultipartRequest (webRequest );
111+ return (multipartRequest != null ? multipartRequest .getFileMap () : new LinkedHashMap <>(0 ));
112+ }
113+ else if (valueType == Part .class ) {
114+ HttpServletRequest servletRequest = webRequest .getNativeRequest (HttpServletRequest .class );
115+ if (servletRequest != null && MultipartResolutionDelegate .isMultipartRequest (servletRequest )) {
116+ Collection <Part > parts = servletRequest .getParts ();
117+ LinkedHashMap <String , Part > result = new LinkedHashMap <>(parts .size ());
118+ for (Part part : parts ) {
119+ if (!result .containsKey (part .getName ())) {
120+ result .put (part .getName (), part );
121+ }
122+ }
123+ return result ;
79124 }
80- });
81- return result ;
125+ return new LinkedHashMap <>(0 );
126+ }
127+ else {
128+ Map <String , String []> parameterMap = webRequest .getParameterMap ();
129+ Map <String , String > result = new LinkedHashMap <>(parameterMap .size ());
130+ parameterMap .forEach ((key , values ) -> {
131+ if (values .length > 0 ) {
132+ result .put (key , values [0 ]);
133+ }
134+ });
135+ return result ;
136+ }
82137 }
83138 }
139+
84140}
0 commit comments