Support for @RequestParam Map declared with MultipartFile/Part values

Issue: SPR-17405
This commit is contained in:
Juergen Hoeller
2018-10-24 20:44:58 +02:00
parent 488a1d4561
commit f0f1979fc5
4 changed files with 247 additions and 96 deletions

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2017 the original author or authors.
* Copyright 2002-2018 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.
@@ -18,74 +18,68 @@ package org.springframework.web.method.annotation;
import java.util.Collections;
import java.util.Map;
import javax.servlet.http.Part;
import org.junit.Before;
import org.junit.Test;
import org.springframework.core.MethodParameter;
import org.springframework.mock.web.test.MockHttpServletRequest;
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.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.context.request.NativeWebRequest;
import org.springframework.web.context.request.ServletWebRequest;
import org.springframework.web.method.ResolvableMethod;
import org.springframework.web.multipart.MultipartFile;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import static org.springframework.web.method.MvcAnnotationPredicates.requestParam;
import static org.junit.Assert.*;
import static org.springframework.web.method.MvcAnnotationPredicates.*;
/**
* Test fixture with {@link RequestParamMapMethodArgumentResolver}.
*
* @author Arjen Poutsma
* @author Rossen Stoyanchev
* @author Juergen Hoeller
*/
public class RequestParamMapMethodArgumentResolverTests {
private RequestParamMapMethodArgumentResolver resolver;
private RequestParamMapMethodArgumentResolver resolver = new RequestParamMapMethodArgumentResolver();
private NativeWebRequest webRequest;
private MockHttpServletRequest request = new MockHttpServletRequest();
private MockHttpServletRequest request;
private NativeWebRequest webRequest = new ServletWebRequest(request, new MockHttpServletResponse());
private ResolvableMethod testMethod = ResolvableMethod.on(getClass()).named("handle").build();
@Before
public void setUp() throws Exception {
resolver = new RequestParamMapMethodArgumentResolver();
request = new MockHttpServletRequest();
webRequest = new ServletWebRequest(request, new MockHttpServletResponse());
}
@Test
public void supportsParameter() {
MethodParameter param = this.testMethod.annot(requestParam().noName()).arg(Map.class);
MethodParameter param = this.testMethod.annot(requestParam().noName()).arg(Map.class, String.class, String.class);
assertTrue(resolver.supportsParameter(param));
param = this.testMethod.annotPresent(RequestParam.class).arg(MultiValueMap.class);
param = this.testMethod.annotPresent(RequestParam.class).arg(MultiValueMap.class, String.class, String.class);
assertTrue(resolver.supportsParameter(param));
param = this.testMethod.annot(requestParam().name("name")).arg(Map.class);
param = this.testMethod.annot(requestParam().name("name")).arg(Map.class, String.class, String.class);
assertFalse(resolver.supportsParameter(param));
param = this.testMethod.annotNotPresent(RequestParam.class).arg(Map.class);
param = this.testMethod.annotNotPresent(RequestParam.class).arg(Map.class, String.class, String.class);
assertFalse(resolver.supportsParameter(param));
}
@Test
public void resolveMapArgument() throws Exception {
public void resolveMapOfString() throws Exception {
String name = "foo";
String value = "bar";
request.addParameter(name, value);
Map<String, String> expected = Collections.singletonMap(name, value);
MethodParameter param = this.testMethod.annot(requestParam().noName()).arg(Map.class);
MethodParameter param = this.testMethod.annot(requestParam().noName()).arg(Map.class, String.class, String.class);
Object result = resolver.resolveArgument(param, null, webRequest, null);
assertTrue(result instanceof Map);
@@ -93,7 +87,7 @@ public class RequestParamMapMethodArgumentResolverTests {
}
@Test
public void resolveMultiValueMapArgument() throws Exception {
public void resolveMultiValueMapOfString() throws Exception {
String name = "foo";
String value1 = "bar";
String value2 = "baz";
@@ -103,19 +97,115 @@ public class RequestParamMapMethodArgumentResolverTests {
expected.add(name, value1);
expected.add(name, value2);
MethodParameter param = this.testMethod.annotPresent(RequestParam.class).arg(MultiValueMap.class);
MethodParameter param = this.testMethod.annotPresent(RequestParam.class).arg(MultiValueMap.class, String.class, String.class);
Object result = resolver.resolveArgument(param, null, webRequest, null);
assertTrue(result instanceof MultiValueMap);
assertEquals("Invalid result", expected, result);
}
@Test
@SuppressWarnings("unchecked")
public void resolveMapOfMultipartFile() throws Exception {
MockMultipartHttpServletRequest request = new MockMultipartHttpServletRequest();
MultipartFile expected1 = new MockMultipartFile("mfile", "Hello World".getBytes());
MultipartFile expected2 = new MockMultipartFile("other", "Hello World 3".getBytes());
request.addFile(expected1);
request.addFile(expected2);
webRequest = new ServletWebRequest(request);
MethodParameter param = this.testMethod.annot(requestParam().noName()).arg(Map.class, String.class, MultipartFile.class);
Object result = resolver.resolveArgument(param, null, webRequest, null);
assertTrue(result instanceof Map);
Map<String, MultipartFile> resultMap = (Map<String, MultipartFile>) result;
assertEquals(2, resultMap.size());
assertEquals(expected1, resultMap.get("mfile"));
assertEquals(expected2, resultMap.get("other"));
}
@Test
@SuppressWarnings("unchecked")
public void resolveMultiValueMapOfMultipartFile() throws Exception {
MockMultipartHttpServletRequest request = new MockMultipartHttpServletRequest();
MultipartFile expected1 = new MockMultipartFile("mfilelist", "Hello World 1".getBytes());
MultipartFile expected2 = new MockMultipartFile("mfilelist", "Hello World 2".getBytes());
MultipartFile expected3 = new MockMultipartFile("other", "Hello World 3".getBytes());
request.addFile(expected1);
request.addFile(expected2);
request.addFile(expected3);
webRequest = new ServletWebRequest(request);
MethodParameter param = this.testMethod.annot(requestParam().noName()).arg(MultiValueMap.class, String.class, MultipartFile.class);
Object result = resolver.resolveArgument(param, null, webRequest, null);
assertTrue(result instanceof MultiValueMap);
MultiValueMap<String, MultipartFile> resultMap = (MultiValueMap<String, MultipartFile>) result;
assertEquals(2, resultMap.size());
assertEquals(2, resultMap.get("mfilelist").size());
assertEquals(expected1, resultMap.get("mfilelist").get(0));
assertEquals(expected2, resultMap.get("mfilelist").get(1));
assertEquals(1, resultMap.get("other").size());
assertEquals(expected3, resultMap.get("other").get(0));
}
@Test
@SuppressWarnings("unchecked")
public void resolveMapOfPart() throws Exception {
MockHttpServletRequest request = new MockHttpServletRequest();
request.setContentType("multipart/form-data");
Part expected1 = new MockPart("mfile", "Hello World".getBytes());
Part expected2 = new MockPart("other", "Hello World 3".getBytes());
request.addPart(expected1);
request.addPart(expected2);
webRequest = new ServletWebRequest(request);
MethodParameter param = this.testMethod.annot(requestParam().noName()).arg(Map.class, String.class, Part.class);
Object result = resolver.resolveArgument(param, null, webRequest, null);
assertTrue(result instanceof Map);
Map<String, Part> resultMap = (Map<String, Part>) result;
assertEquals(2, resultMap.size());
assertEquals(expected1, resultMap.get("mfile"));
assertEquals(expected2, resultMap.get("other"));
}
@Test
@SuppressWarnings("unchecked")
public void resolveMultiValueMapOfPart() throws Exception {
MockHttpServletRequest request = new MockHttpServletRequest();
request.setContentType("multipart/form-data");
Part expected1 = new MockPart("mfilelist", "Hello World 1".getBytes());
Part expected2 = new MockPart("mfilelist", "Hello World 2".getBytes());
Part expected3 = new MockPart("other", "Hello World 3".getBytes());
request.addPart(expected1);
request.addPart(expected2);
request.addPart(expected3);
webRequest = new ServletWebRequest(request);
MethodParameter param = this.testMethod.annot(requestParam().noName()).arg(MultiValueMap.class, String.class, Part.class);
Object result = resolver.resolveArgument(param, null, webRequest, null);
assertTrue(result instanceof MultiValueMap);
MultiValueMap<String, Part> resultMap = (MultiValueMap<String, Part>) result;
assertEquals(2, resultMap.size());
assertEquals(2, resultMap.get("mfilelist").size());
assertEquals(expected1, resultMap.get("mfilelist").get(0));
assertEquals(expected2, resultMap.get("mfilelist").get(1));
assertEquals(1, resultMap.get("other").size());
assertEquals(expected3, resultMap.get("other").get(0));
}
public void handle(
@RequestParam Map<?, ?> param1,
@RequestParam MultiValueMap<?, ?> param2,
@RequestParam("name") Map<?, ?> param3,
Map<?, ?> param4) {
@RequestParam Map<String, String> param1,
@RequestParam MultiValueMap<String, String> param2,
@RequestParam Map<String, MultipartFile> param3,
@RequestParam MultiValueMap<String, MultipartFile> param4,
@RequestParam Map<String, Part> param5,
@RequestParam MultiValueMap<String, Part> param6,
@RequestParam("name") Map<String, String> param7,
Map<String, String> param8) {
}
}