Skip to content

Commit c2625f9

Browse files
committed
Properly handle single-value map with @MatrixVariable
Issue: SPR-14294
1 parent 400206a commit c2625f9

File tree

3 files changed

+31
-15
lines changed

3 files changed

+31
-15
lines changed

spring-webmvc/src/main/java/org/springframework/web/servlet/mvc/method/annotation/MatrixVariableMapMethodArgumentResolver.java

+26-10
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2015 the original author or authors.
2+
* Copyright 2002-2016 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -17,9 +17,11 @@
1717
package org.springframework.web.servlet.mvc.method.annotation;
1818

1919
import java.util.Collections;
20+
import java.util.List;
2021
import java.util.Map;
2122

2223
import org.springframework.core.MethodParameter;
24+
import org.springframework.core.ResolvableType;
2325
import org.springframework.util.CollectionUtils;
2426
import org.springframework.util.LinkedMultiValueMap;
2527
import org.springframework.util.MultiValueMap;
@@ -68,23 +70,37 @@ public Object resolveArgument(MethodParameter parameter, ModelAndViewContainer m
6870
return Collections.emptyMap();
6971
}
7072

73+
MultiValueMap<String, String> map = new LinkedMultiValueMap<String, String>();
7174
String pathVariable = parameter.getParameterAnnotation(MatrixVariable.class).pathVar();
7275

7376
if (!pathVariable.equals(ValueConstants.DEFAULT_NONE)) {
74-
MultiValueMap<String, String> map = matrixVariables.get(pathVariable);
75-
return (map != null) ? map : Collections.emptyMap();
77+
MultiValueMap<String, String> mapForPathVariable = matrixVariables.get(pathVariable);
78+
if (mapForPathVariable == null) {
79+
return Collections.emptyMap();
80+
}
81+
map.putAll(mapForPathVariable);
7682
}
77-
78-
MultiValueMap<String, String> map = new LinkedMultiValueMap<String, String>();
79-
for (MultiValueMap<String, String> vars : matrixVariables.values()) {
80-
for (String name : vars.keySet()) {
81-
for (String value : vars.get(name)) {
82-
map.add(name, value);
83+
else {
84+
for (MultiValueMap<String, String> vars : matrixVariables.values()) {
85+
for (String name : vars.keySet()) {
86+
for (String value : vars.get(name)) {
87+
map.add(name, value);
88+
}
8389
}
8490
}
8591
}
8692

87-
return map;
93+
return (isSingleValueMap(parameter) ? map.toSingleValueMap() : map);
94+
}
95+
96+
private boolean isSingleValueMap(MethodParameter parameter) {
97+
if (!MultiValueMap.class.isAssignableFrom(parameter.getParameterType())) {
98+
ResolvableType[] genericTypes = ResolvableType.forMethodParameter(parameter).getGenerics();
99+
if (genericTypes.length == 2) {
100+
return !List.class.isAssignableFrom(genericTypes[1].getRawClass());
101+
}
102+
}
103+
return false;
88104
}
89105

90106
}

spring-webmvc/src/test/java/org/springframework/web/servlet/mvc/method/annotation/MatrixVariablesMapMethodArgumentResolverTests.java

+3-3
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2015 the original author or authors.
2+
* Copyright 2002-2016 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -102,7 +102,7 @@ public void resolveArgument() throws Exception {
102102
Map<String, String> map = (Map<String, String>) this.resolver.resolveArgument(
103103
this.paramMap, this.mavContainer, this.webRequest, null);
104104

105-
assertEquals(Arrays.asList("red", "green", "blue"), map.get("colors"));
105+
assertEquals("red", map.get("colors"));
106106

107107
@SuppressWarnings("unchecked")
108108
MultiValueMap<String, String> multivalueMap = (MultiValueMap<String, String>) this.resolver.resolveArgument(
@@ -131,7 +131,7 @@ public void resolveArgumentPathVariable() throws Exception {
131131
Map<String, String> mapAll = (Map<String, String>) this.resolver.resolveArgument(
132132
this.paramMap, this.mavContainer, this.webRequest, null);
133133

134-
assertEquals(Arrays.asList("red", "purple", "yellow", "orange"), mapAll.get("colors"));
134+
assertEquals("red", mapAll.get("colors"));
135135
}
136136

137137
@Test

src/asciidoc/web-mvc.adoc

+2-2
Original file line numberDiff line numberDiff line change
@@ -1026,8 +1026,8 @@ All matrix variables may be obtained in a Map:
10261026
10271027
@RequestMapping(path = "/owners/{ownerId}/pets/{petId}", method = RequestMethod.GET)
10281028
public void findPet(
1029-
@MatrixVariable Map<String, String> matrixVars,
1030-
@MatrixVariable(pathVar="petId"") Map<String, String> petMatrixVars) {
1029+
@MatrixVariable MultiValueMap<String, String> matrixVars,
1030+
@MatrixVariable(pathVar="petId"") MultiValueMap<String, String> petMatrixVars) {
10311031
10321032
// matrixVars: ["q" : [11,22], "r" : 12, "s" : 23]
10331033
// petMatrixVars: ["q" : 11, "s" : 23]

0 commit comments

Comments
 (0)