From ea10ee5265f3d3175b6dad127cb7d4c3a407066b Mon Sep 17 00:00:00 2001 From: Dmytro Nosan Date: Wed, 12 Jun 2019 15:49:19 +0300 Subject: [PATCH] queryParam and replaceParam with List See gh-23114 --- .../web/util/DefaultUriBuilderFactory.java | 13 ++++++ .../springframework/web/util/UriBuilder.java | 27 +++++++++++- .../web/util/UriComponentsBuilder.java | 42 +++++++++++++++++-- .../web/util/UriComponentsBuilderTests.java | 41 +++++++++++++++++- 4 files changed, 118 insertions(+), 5 deletions(-) diff --git a/spring-web/src/main/java/org/springframework/web/util/DefaultUriBuilderFactory.java b/spring-web/src/main/java/org/springframework/web/util/DefaultUriBuilderFactory.java index 428b8e5bad..4c3c0e5d75 100644 --- a/spring-web/src/main/java/org/springframework/web/util/DefaultUriBuilderFactory.java +++ b/spring-web/src/main/java/org/springframework/web/util/DefaultUriBuilderFactory.java @@ -17,6 +17,7 @@ package org.springframework.web.util; import java.net.URI; +import java.util.Collection; import java.util.Collections; import java.util.HashMap; import java.util.Map; @@ -326,12 +327,24 @@ public class DefaultUriBuilderFactory implements UriBuilderFactory { return this; } + @Override + public DefaultUriBuilder queryParams(String name, @Nullable Collection values) { + this.uriComponentsBuilder.queryParams(name, values); + return this; + } + @Override public DefaultUriBuilder replaceQueryParam(String name, Object... values) { this.uriComponentsBuilder.replaceQueryParam(name, values); return this; } + @Override + public DefaultUriBuilder replaceQueryParams(String name, @Nullable Collection values) { + this.uriComponentsBuilder.replaceQueryParams(name, values); + return this; + } + @Override public DefaultUriBuilder queryParams(MultiValueMap params) { this.uriComponentsBuilder.queryParams(params); diff --git a/spring-web/src/main/java/org/springframework/web/util/UriBuilder.java b/spring-web/src/main/java/org/springframework/web/util/UriBuilder.java index f0b8f1dcc7..d91903856d 100644 --- a/spring-web/src/main/java/org/springframework/web/util/UriBuilder.java +++ b/spring-web/src/main/java/org/springframework/web/util/UriBuilder.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2018 the original author or authors. + * Copyright 2002-2019 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,6 +17,7 @@ package org.springframework.web.util; import java.net.URI; +import java.util.Collection; import java.util.Map; import org.springframework.lang.Nullable; @@ -124,9 +125,22 @@ public interface UriBuilder { * only (i.e. {@code ?foo} instead of {@code ?foo=bar}. * @param name the query parameter name * @param values the query parameter values + * @see #queryParams(String, Collection) */ UriBuilder queryParam(String name, Object... values); + /** + * Append the given query parameter to the existing query parameters. The + * given name or any of the values may contain URI template variables. If no + * values are given, the resulting URI will contain the query parameter name + * only (i.e. {@code ?foo} instead of {@code ?foo=bar}. + * @param name the query parameter name + * @param values the query parameter values + * @since 5.2.0 + * @see #queryParam(String, Object...) + */ + UriBuilder queryParams(String name, @Nullable Collection values); + /** * Add the given query parameters. * @param params the params @@ -138,9 +152,20 @@ public interface UriBuilder { * the same parameter. If no values are given, the query parameter is removed. * @param name the query parameter name * @param values the query parameter values + * @see #replaceQueryParams(String, Collection) */ UriBuilder replaceQueryParam(String name, Object... values); + /** + * Set the query parameter values overriding all existing query values for + * the same parameter. If no values are given, the query parameter is removed. + * @param name the query parameter name + * @param values the query parameter values + * @since 5.2.0 + * @see #replaceQueryParam(String, Object...) + */ + UriBuilder replaceQueryParams(String name, @Nullable Collection values); + /** * Set the query parameter values overriding all existing query values. * @param params the query parameter name 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 5e3db7e8ef..779fd4bd8b 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 @@ -20,6 +20,9 @@ import java.net.URI; import java.nio.charset.Charset; import java.nio.charset.StandardCharsets; import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.Collections; import java.util.HashMap; import java.util.LinkedList; import java.util.List; @@ -31,6 +34,7 @@ import org.springframework.http.HttpHeaders; import org.springframework.http.HttpRequest; import org.springframework.lang.Nullable; import org.springframework.util.Assert; +import org.springframework.util.CollectionUtils; import org.springframework.util.LinkedMultiValueMap; import org.springframework.util.MultiValueMap; import org.springframework.util.ObjectUtils; @@ -696,11 +700,28 @@ public class UriComponentsBuilder implements UriBuilder, Cloneable { * @param name the query parameter name * @param values the query parameter values * @return this UriComponentsBuilder + * @see #queryParams(String, Collection) */ @Override public UriComponentsBuilder queryParam(String name, Object... values) { + return queryParams(name, (!ObjectUtils.isEmpty(values) ? Arrays.asList(values) : Collections.emptyList())); + } + + /** + * Append the given query parameter to the existing query parameters. The + * given name or any of the values may contain URI template variables. If no + * values are given, the resulting URI will contain the query parameter name + * only (i.e. {@code ?foo} instead of {@code ?foo=bar}). + * @param name the query parameter name + * @param values the query parameter values + * @return this UriComponentsBuilder + * @since 5.2.0 + * @see #queryParam(String, Object...) + */ + @Override + public UriComponentsBuilder queryParams(String name, @Nullable Collection values) { Assert.notNull(name, "Name must not be null"); - if (!ObjectUtils.isEmpty(values)) { + if (!CollectionUtils.isEmpty(values)) { for (Object value : values) { String valueAsString = (value != null ? value.toString() : null); this.queryParams.add(name, valueAsString); @@ -733,13 +754,28 @@ public class UriComponentsBuilder implements UriBuilder, Cloneable { * @param name the query parameter name * @param values the query parameter values * @return this UriComponentsBuilder + * @see #replaceQueryParams(String, Collection) */ @Override public UriComponentsBuilder replaceQueryParam(String name, Object... values) { + return replaceQueryParams(name, (!ObjectUtils.isEmpty(values) ? Arrays.asList(values) : Collections.emptyList())); + } + + /** + * Set the query parameter values overriding all existing query values for + * the same parameter. If no values are given, the query parameter is removed. + * @param name the query parameter name + * @param values the query parameter values + * @return this UriComponentsBuilder + * @see #replaceQueryParam(String, Object...) + * @since 5.2.0 + */ + @Override + public UriComponentsBuilder replaceQueryParams(String name, @Nullable Collection values) { Assert.notNull(name, "Name must not be null"); this.queryParams.remove(name); - if (!ObjectUtils.isEmpty(values)) { - queryParam(name, values); + if (!CollectionUtils.isEmpty(values)) { + queryParams(name, values); } resetSchemeSpecificPart(); 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 c580a5beb9..d785c16e95 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 @@ -643,7 +643,7 @@ public class UriComponentsBuilderTests { } @Test - public void queryParams() { + public void queryParam() { UriComponentsBuilder builder = UriComponentsBuilder.newInstance(); UriComponents result = builder.queryParam("baz", "qux", 42).build(); @@ -654,6 +654,18 @@ public class UriComponentsBuilderTests { assertThat(result.getQueryParams()).isEqualTo(expectedQueryParams); } + @Test + public void queryParams() { + UriComponentsBuilder builder = UriComponentsBuilder.newInstance(); + UriComponents result = builder.queryParams("baz", Arrays.asList("qux", 42)).build(); + + assertThat(result.getQuery()).isEqualTo("baz=qux&baz=42"); + MultiValueMap expectedQueryParams = new LinkedMultiValueMap<>(2); + expectedQueryParams.add("baz", "qux"); + expectedQueryParams.add("baz", "42"); + assertThat(result.getQueryParams()).isEqualTo(expectedQueryParams); + } + @Test public void emptyQueryParam() { UriComponentsBuilder builder = UriComponentsBuilder.newInstance(); @@ -665,6 +677,18 @@ public class UriComponentsBuilderTests { assertThat(result.getQueryParams()).isEqualTo(expectedQueryParams); } + @Test + public void emptyQueryParams() { + UriComponentsBuilder builder = UriComponentsBuilder.newInstance(); + UriComponents result = builder.queryParams("baz", Collections.emptyList()).queryParams("foo", null).build(); + + assertThat(result.getQuery()).isEqualTo("baz&foo"); + MultiValueMap expectedQueryParams = new LinkedMultiValueMap<>(2); + expectedQueryParams.add("baz", null); + expectedQueryParams.add("foo", null); + assertThat(result.getQueryParams()).isEqualTo(expectedQueryParams); + } + @Test public void replaceQueryParam() { UriComponentsBuilder builder = UriComponentsBuilder.newInstance().queryParam("baz", "qux", 42); @@ -680,6 +704,21 @@ public class UriComponentsBuilderTests { assertThat(result.getQuery()).as("Query param should have been deleted").isNull(); } + @Test + public void replaceQueryParams() { + UriComponentsBuilder builder = UriComponentsBuilder.newInstance().queryParams("baz", Arrays.asList("qux", 42)); + builder.replaceQueryParams("baz", Arrays.asList("xuq", 24)); + UriComponents result = builder.build(); + + assertThat(result.getQuery()).isEqualTo("baz=xuq&baz=24"); + + builder = UriComponentsBuilder.newInstance().queryParams("baz", Arrays.asList("qux", 42)); + builder.replaceQueryParams("baz", Collections.emptyList()); + result = builder.build(); + + assertThat(result.getQuery()).as("Query param should have been deleted").isNull(); + } + @Test public void buildAndExpandHierarchical() { UriComponents result = UriComponentsBuilder.fromPath("/{foo}").buildAndExpand("fooValue");