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 1b90021c28d..0438faaf7c9 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 @@ -21,6 +21,7 @@ import java.util.Collection; import java.util.Collections; import java.util.HashMap; import java.util.Map; +import java.util.Optional; import org.springframework.lang.Nullable; import org.springframework.util.MultiValueMap; @@ -334,6 +335,12 @@ public class DefaultUriBuilderFactory implements UriBuilderFactory { return this; } + @Override + public DefaultUriBuilder queryParamIfPresent(String name, Optional optionalValue) { + this.uriComponentsBuilder.queryParamIfPresent(name, optionalValue); + return this; + } + @Override public DefaultUriBuilder queryParam(String name, @Nullable Collection values) { this.uriComponentsBuilder.queryParam(name, values); 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 fbd04de36a1..c5b69c55bd5 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 @@ -19,6 +19,7 @@ package org.springframework.web.util; import java.net.URI; import java.util.Collection; import java.util.Map; +import java.util.Optional; import org.springframework.lang.Nullable; import org.springframework.util.MultiValueMap; @@ -185,6 +186,15 @@ public interface UriBuilder { */ UriBuilder queryParam(String name, Object... values); + /** + * Delegates to {@link #queryParam(String, Object...)} or {@link #queryParam(String, Object...)} if and only if optionalValue has a value. + * No action will be taken, and the query parameter name will not be added, if optionalValue is empty. + * @param name the query parameter name + * @param optionalValue an Optional, either empty or holding the query parameter value. + * @return + */ + UriBuilder queryParamIfPresent(String name, Optional optionalValue); + /** * Variant of {@link #queryParam(String, Object...)} with a Collection. *

Note: please, review the Javadoc of 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 f9ea2fc69e5..672989dd3bf 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 @@ -27,6 +27,7 @@ import java.util.Deque; import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.Optional; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -708,6 +709,20 @@ public class UriComponentsBuilder implements UriBuilder, Cloneable { return this; } + @Override + public UriComponentsBuilder queryParamIfPresent(String name, Optional optionalValue) { + if (optionalValue.isPresent()) { + Object value = optionalValue.get(); + if (value instanceof Collection) { + queryParam(name, (Collection) value); + } + else { + queryParam(name, value); + } + } + return this; + } + @Override public UriComponentsBuilder queryParam(String name, @Nullable Collection values) { return queryParam(name, (CollectionUtils.isEmpty(values) ? EMPTY_VALUES : values.toArray())); 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 b7e11ea267d..2e2e37c90bf 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 @@ -18,11 +18,13 @@ package org.springframework.web.util; import java.net.URI; import java.net.URISyntaxException; +import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.Collections; import java.util.HashMap; import java.util.Map; +import java.util.Optional; import org.junit.jupiter.api.Test; @@ -204,6 +206,33 @@ class UriComponentsBuilderTests { assertThat(uri.toString()).isEqualTo(httpUrl); } + + @Test + void queryParamIfPresent() { + UriComponentsBuilder builder = UriComponentsBuilder.newInstance(); + UriComponents result = builder.queryParamIfPresent("baz", Optional.of("qux")).queryParamIfPresent("foo", Optional.empty()).build(); + + assertThat(result.getQuery()).isEqualTo("baz=qux"); + MultiValueMap expectedQueryParams = new LinkedMultiValueMap<>(1); + expectedQueryParams.add("baz", "qux"); + assertThat(result.getQueryParams()).isEqualTo(expectedQueryParams); + } + + @Test + void queryParamIfPresentCollection() { + Collection c = new ArrayList<>(); + c.add("foo"); + c.add("bar"); + UriComponentsBuilder builder = UriComponentsBuilder.newInstance(); + UriComponents result = builder.queryParamIfPresent("baz", Optional.of(c)).build(); + + assertThat(result.getQuery()).isEqualTo("baz=foo&baz=bar"); + MultiValueMap expectedQueryParams = new LinkedMultiValueMap<>(1); + expectedQueryParams.add("baz", "foo"); + expectedQueryParams.add("baz", "bar"); + assertThat(result.getQueryParams()).isEqualTo(expectedQueryParams); + } + @Test // SPR-10539 void fromUriStringIPv6Host() { UriComponents result = UriComponentsBuilder