diff --git a/spring-webmvc/src/main/java/org/springframework/web/servlet/mvc/method/annotation/MatrixVariableMapMethodArgumentResolver.java b/spring-webmvc/src/main/java/org/springframework/web/servlet/mvc/method/annotation/MatrixVariableMapMethodArgumentResolver.java index 59a8e9874f..212a826902 100644 --- a/spring-webmvc/src/main/java/org/springframework/web/servlet/mvc/method/annotation/MatrixVariableMapMethodArgumentResolver.java +++ b/spring-webmvc/src/main/java/org/springframework/web/servlet/mvc/method/annotation/MatrixVariableMapMethodArgumentResolver.java @@ -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,9 +17,11 @@ package org.springframework.web.servlet.mvc.method.annotation; import java.util.Collections; +import java.util.List; import java.util.Map; import org.springframework.core.MethodParameter; +import org.springframework.core.ResolvableType; import org.springframework.util.CollectionUtils; import org.springframework.util.LinkedMultiValueMap; import org.springframework.util.MultiValueMap; @@ -68,23 +70,37 @@ public class MatrixVariableMapMethodArgumentResolver implements HandlerMethodArg return Collections.emptyMap(); } + MultiValueMap map = new LinkedMultiValueMap(); String pathVariable = parameter.getParameterAnnotation(MatrixVariable.class).pathVar(); if (!pathVariable.equals(ValueConstants.DEFAULT_NONE)) { - MultiValueMap map = matrixVariables.get(pathVariable); - return (map != null) ? map : Collections.emptyMap(); + MultiValueMap mapForPathVariable = matrixVariables.get(pathVariable); + if (mapForPathVariable == null) { + return Collections.emptyMap(); + } + map.putAll(mapForPathVariable); } - - MultiValueMap map = new LinkedMultiValueMap(); - for (MultiValueMap vars : matrixVariables.values()) { - for (String name : vars.keySet()) { - for (String value : vars.get(name)) { - map.add(name, value); + else { + for (MultiValueMap vars : matrixVariables.values()) { + for (String name : vars.keySet()) { + for (String value : vars.get(name)) { + map.add(name, value); + } } } } - return map; + return (isSingleValueMap(parameter) ? map.toSingleValueMap() : map); + } + + private boolean isSingleValueMap(MethodParameter parameter) { + if (!MultiValueMap.class.isAssignableFrom(parameter.getParameterType())) { + ResolvableType[] genericTypes = ResolvableType.forMethodParameter(parameter).getGenerics(); + if (genericTypes.length == 2) { + return !List.class.isAssignableFrom(genericTypes[1].getRawClass()); + } + } + return false; } } \ No newline at end of file diff --git a/spring-webmvc/src/test/java/org/springframework/web/servlet/mvc/method/annotation/MatrixVariablesMapMethodArgumentResolverTests.java b/spring-webmvc/src/test/java/org/springframework/web/servlet/mvc/method/annotation/MatrixVariablesMapMethodArgumentResolverTests.java index f4fe3ac364..fdf6c65218 100644 --- a/spring-webmvc/src/test/java/org/springframework/web/servlet/mvc/method/annotation/MatrixVariablesMapMethodArgumentResolverTests.java +++ b/spring-webmvc/src/test/java/org/springframework/web/servlet/mvc/method/annotation/MatrixVariablesMapMethodArgumentResolverTests.java @@ -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. @@ -102,7 +102,7 @@ public class MatrixVariablesMapMethodArgumentResolverTests { Map map = (Map) this.resolver.resolveArgument( this.paramMap, this.mavContainer, this.webRequest, null); - assertEquals(Arrays.asList("red", "green", "blue"), map.get("colors")); + assertEquals("red", map.get("colors")); @SuppressWarnings("unchecked") MultiValueMap multivalueMap = (MultiValueMap) this.resolver.resolveArgument( @@ -131,7 +131,7 @@ public class MatrixVariablesMapMethodArgumentResolverTests { Map mapAll = (Map) this.resolver.resolveArgument( this.paramMap, this.mavContainer, this.webRequest, null); - assertEquals(Arrays.asList("red", "purple", "yellow", "orange"), mapAll.get("colors")); + assertEquals("red", mapAll.get("colors")); } @Test diff --git a/src/asciidoc/web-mvc.adoc b/src/asciidoc/web-mvc.adoc index 9489249b45..c0b7c8cb0e 100644 --- a/src/asciidoc/web-mvc.adoc +++ b/src/asciidoc/web-mvc.adoc @@ -1026,8 +1026,8 @@ All matrix variables may be obtained in a Map: @RequestMapping(path = "/owners/{ownerId}/pets/{petId}", method = RequestMethod.GET) public void findPet( - @MatrixVariable Map matrixVars, - @MatrixVariable(pathVar="petId"") Map petMatrixVars) { + @MatrixVariable MultiValueMap matrixVars, + @MatrixVariable(pathVar="petId"") MultiValueMap petMatrixVars) { // matrixVars: ["q" : [11,22], "r" : 12, "s" : 23] // petMatrixVars: ["q" : 11, "s" : 23]