diff --git a/spring-webmvc/src/main/java/org/springframework/web/servlet/function/DefaultServerRequest.java b/spring-webmvc/src/main/java/org/springframework/web/servlet/function/DefaultServerRequest.java index f0a1e520cb3..f386a3abfc5 100644 --- a/spring-webmvc/src/main/java/org/springframework/web/servlet/function/DefaultServerRequest.java +++ b/spring-webmvc/src/main/java/org/springframework/web/servlet/function/DefaultServerRequest.java @@ -33,6 +33,7 @@ import java.util.Collection; import java.util.Collections; import java.util.Enumeration; import java.util.Iterator; +import java.util.LinkedHashSet; import java.util.List; import java.util.Locale; import java.util.Map; @@ -443,7 +444,7 @@ class DefaultServerRequest implements ServerRequest { List value = Arrays.asList(entry.getValue()); return new SimpleImmutableEntry<>(entry.getKey(), value); }) - .collect(Collectors.toSet()); + .collect(Collectors.toCollection(LinkedHashSet::new)); } @Override diff --git a/spring-webmvc/src/test/java/org/springframework/web/servlet/function/DefaultServerRequestTests.java b/spring-webmvc/src/test/java/org/springframework/web/servlet/function/DefaultServerRequestTests.java index 63256433b16..81ee930ba5c 100644 --- a/spring-webmvc/src/test/java/org/springframework/web/servlet/function/DefaultServerRequestTests.java +++ b/spring-webmvc/src/test/java/org/springframework/web/servlet/function/DefaultServerRequestTests.java @@ -167,6 +167,20 @@ class DefaultServerRequestTests { assertThat(request.param("foo")).contains("bar"); } + @Test // gh-36966 + void paramsEntrySetPreservesOrder() { + MockHttpServletRequest servletRequest = PathPatternsTestUtils.initRequest("GET", "/", true); + servletRequest.setParameter("charlie", "3"); + servletRequest.setParameter("alpha", "1"); + servletRequest.setParameter("bravo", "2"); + + DefaultServerRequest request = new DefaultServerRequest(servletRequest, this.messageConverters); + + assertThat(request.params().entrySet()) + .extracting(Map.Entry::getKey) + .containsExactly("charlie", "alpha", "bravo"); + } + @Test void multipartData() throws Exception { MockPart formPart = new MockPart("form", "foo".getBytes(UTF_8));