From c06b9525ac780f4020d9d78059633eba9b887de6 Mon Sep 17 00:00:00 2001 From: Juergen Hoeller Date: Mon, 10 Sep 2018 11:31:37 +0200 Subject: [PATCH] UriComponentsBuilder copies query params through MultiValueMap.addAll Issue: SPR-17256 --- .../org/springframework/util/LinkedMultiValueMap.java | 8 +++++++- .../springframework/web/util/UriComponentsBuilder.java | 2 +- .../web/util/UriComponentsBuilderTests.java | 7 +++++++ 3 files changed, 15 insertions(+), 2 deletions(-) diff --git a/spring-core/src/main/java/org/springframework/util/LinkedMultiValueMap.java b/spring-core/src/main/java/org/springframework/util/LinkedMultiValueMap.java index e69769e862..7dd97af0f3 100644 --- a/spring-core/src/main/java/org/springframework/util/LinkedMultiValueMap.java +++ b/spring-core/src/main/java/org/springframework/util/LinkedMultiValueMap.java @@ -119,7 +119,6 @@ public class LinkedMultiValueMap implements MultiValueMap, Serializa public Map toSingleValueMap() { LinkedHashMap singleValueMap = new LinkedHashMap<>(this.targetMap.size()); this.targetMap.forEach((key, value) -> singleValueMap.put(key, value.get(0))); - return singleValueMap; } @@ -193,7 +192,10 @@ public class LinkedMultiValueMap implements MultiValueMap, Serializa /** * Create a deep copy of this Map. * @return a copy of this Map, including a copy of each value-holding List entry + * (consistently using an independent modifiable {@link LinkedList} for each entry) + * along the lines of {@code MultiValueMap.addAll} semantics * @since 4.2 + * @see #addAll(MultiValueMap) * @see #clone() */ public LinkedMultiValueMap deepCopy() { @@ -205,7 +207,11 @@ public class LinkedMultiValueMap implements MultiValueMap, Serializa /** * Create a regular copy of this Map. * @return a shallow copy of this Map, reusing this Map's value-holding List entries + * (even if some entries are shared or unmodifiable) along the lines of standard + * {@code Map.put} semantics * @since 4.2 + * @see #put(Object, List) + * @see #putAll(Map) * @see LinkedMultiValueMap#LinkedMultiValueMap(Map) * @see #deepCopy() */ diff --git a/spring-web/src/main/java/org/springframework/web/util/UriComponentsBuilder.java b/spring-web/src/main/java/org/springframework/web/util/UriComponentsBuilder.java index 008a6c3358..c1e59f2fec 100644 --- a/spring-web/src/main/java/org/springframework/web/util/UriComponentsBuilder.java +++ b/spring-web/src/main/java/org/springframework/web/util/UriComponentsBuilder.java @@ -705,7 +705,7 @@ public class UriComponentsBuilder implements UriBuilder, Cloneable { @Override public UriComponentsBuilder queryParams(@Nullable MultiValueMap params) { if (params != null) { - this.queryParams.putAll(params); + this.queryParams.addAll(params); } return this; } diff --git a/spring-web/src/test/java/org/springframework/web/util/UriComponentsBuilderTests.java b/spring-web/src/test/java/org/springframework/web/util/UriComponentsBuilderTests.java index 74c5e3199d..3dd6baf6ce 100644 --- a/spring-web/src/test/java/org/springframework/web/util/UriComponentsBuilderTests.java +++ b/spring-web/src/test/java/org/springframework/web/util/UriComponentsBuilderTests.java @@ -922,4 +922,11 @@ public class UriComponentsBuilderTests { assertNotEquals(uri1, uri2); } + @Test // SPR-17256 + public void uriComponentsWithQueryParamClone() { + UriComponentsBuilder.fromUriString("http://localhost:8081") + .uriComponents(UriComponentsBuilder.fromUriString("/{path}?sort={sort}").build()) + .queryParam("sort", "another_value").build(); + } + }