Skip to content

Commit 1f5f222

Browse files
committed
Merge branch 'pr/23119'
Closes gh-23119
2 parents 0d3e5db + fbb72ef commit 1f5f222

File tree

4 files changed

+117
-3
lines changed

4 files changed

+117
-3
lines changed

spring-web/src/main/java/org/springframework/web/util/DefaultUriBuilderFactory.java

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
package org.springframework.web.util;
1818

1919
import java.net.URI;
20+
import java.util.Collection;
2021
import java.util.Collections;
2122
import java.util.HashMap;
2223
import java.util.Map;
@@ -326,12 +327,24 @@ public DefaultUriBuilder queryParam(String name, Object... values) {
326327
return this;
327328
}
328329

330+
@Override
331+
public DefaultUriBuilder queryParam(String name, @Nullable Collection<?> values) {
332+
this.uriComponentsBuilder.queryParam(name, values);
333+
return this;
334+
}
335+
329336
@Override
330337
public DefaultUriBuilder replaceQueryParam(String name, Object... values) {
331338
this.uriComponentsBuilder.replaceQueryParam(name, values);
332339
return this;
333340
}
334341

342+
@Override
343+
public DefaultUriBuilder replaceQueryParam(String name, @Nullable Collection<?> values) {
344+
this.uriComponentsBuilder.replaceQueryParam(name, values);
345+
return this;
346+
}
347+
335348
@Override
336349
public DefaultUriBuilder queryParams(MultiValueMap<String, String> params) {
337350
this.uriComponentsBuilder.queryParams(params);

spring-web/src/main/java/org/springframework/web/util/UriBuilder.java

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2018 the original author or authors.
2+
* Copyright 2002-2019 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -17,6 +17,7 @@
1717
package org.springframework.web.util;
1818

1919
import java.net.URI;
20+
import java.util.Collection;
2021
import java.util.Map;
2122

2223
import org.springframework.lang.Nullable;
@@ -124,9 +125,22 @@ public interface UriBuilder {
124125
* only (i.e. {@code ?foo} instead of {@code ?foo=bar}.
125126
* @param name the query parameter name
126127
* @param values the query parameter values
128+
* @see #queryParam(String, Collection)
127129
*/
128130
UriBuilder queryParam(String name, Object... values);
129131

132+
/**
133+
* Append the given query parameter to the existing query parameters. The
134+
* given name or any of the values may contain URI template variables. If no
135+
* values are given, the resulting URI will contain the query parameter name
136+
* only (i.e. {@code ?foo} instead of {@code ?foo=bar}.
137+
* @param name the query parameter name
138+
* @param values the query parameter values
139+
* @since 5.2.0
140+
* @see #queryParam(String, Object...)
141+
*/
142+
UriBuilder queryParam(String name, @Nullable Collection<?> values);
143+
130144
/**
131145
* Add the given query parameters.
132146
* @param params the params
@@ -138,9 +152,20 @@ public interface UriBuilder {
138152
* the same parameter. If no values are given, the query parameter is removed.
139153
* @param name the query parameter name
140154
* @param values the query parameter values
155+
* @see #replaceQueryParam(String, Collection)
141156
*/
142157
UriBuilder replaceQueryParam(String name, Object... values);
143158

159+
/**
160+
* Set the query parameter values overriding all existing query values for
161+
* the same parameter. If no values are given, the query parameter is removed.
162+
* @param name the query parameter name
163+
* @param values the query parameter values
164+
* @since 5.2.0
165+
* @see #replaceQueryParam(String, Object...)
166+
*/
167+
UriBuilder replaceQueryParam(String name, @Nullable Collection<?> values);
168+
144169
/**
145170
* Set the query parameter values overriding all existing query values.
146171
* @param params the query parameter name

spring-web/src/main/java/org/springframework/web/util/UriComponentsBuilder.java

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
import java.nio.charset.Charset;
2121
import java.nio.charset.StandardCharsets;
2222
import java.util.ArrayList;
23+
import java.util.Collection;
2324
import java.util.HashMap;
2425
import java.util.LinkedList;
2526
import java.util.List;
@@ -100,6 +101,8 @@ public class UriComponentsBuilder implements UriBuilder, Cloneable {
100101

101102
private static final Pattern FORWARDED_PROTO_PATTERN = Pattern.compile("proto=\"?([^;,\"]+)\"?");
102103

104+
private static final Object[] EMPTY_VALUES = new Object[0];
105+
103106

104107
@Nullable
105108
private String scheme;
@@ -696,6 +699,7 @@ public UriComponentsBuilder replaceQuery(@Nullable String query) {
696699
* @param name the query parameter name
697700
* @param values the query parameter values
698701
* @return this UriComponentsBuilder
702+
* @see #queryParam(String, Collection)
699703
*/
700704
@Override
701705
public UriComponentsBuilder queryParam(String name, Object... values) {
@@ -713,6 +717,22 @@ public UriComponentsBuilder queryParam(String name, Object... values) {
713717
return this;
714718
}
715719

720+
/**
721+
* Append the given query parameter to the existing query parameters. The
722+
* given name or any of the values may contain URI template variables. If no
723+
* values are given, the resulting URI will contain the query parameter name
724+
* only (i.e. {@code ?foo} instead of {@code ?foo=bar}).
725+
* @param name the query parameter name
726+
* @param values the query parameter values
727+
* @return this UriComponentsBuilder
728+
* @since 5.2.0
729+
* @see #queryParam(String, Object...)
730+
*/
731+
@Override
732+
public UriComponentsBuilder queryParam(String name, @Nullable Collection<?> values) {
733+
return queryParam(name, values != null ? values.toArray() : EMPTY_VALUES);
734+
}
735+
716736
/**
717737
* Add the given query parameters.
718738
* @param params the params
@@ -733,6 +753,7 @@ public UriComponentsBuilder queryParams(@Nullable MultiValueMap<String, String>
733753
* @param name the query parameter name
734754
* @param values the query parameter values
735755
* @return this UriComponentsBuilder
756+
* @see #replaceQueryParam(String, Collection)
736757
*/
737758
@Override
738759
public UriComponentsBuilder replaceQueryParam(String name, Object... values) {
@@ -745,6 +766,20 @@ public UriComponentsBuilder replaceQueryParam(String name, Object... values) {
745766
return this;
746767
}
747768

769+
/**
770+
* Set the query parameter values overriding all existing query values for
771+
* the same parameter. If no values are given, the query parameter is removed.
772+
* @param name the query parameter name
773+
* @param values the query parameter values
774+
* @return this UriComponentsBuilder
775+
* @see #replaceQueryParam(String, Object...)
776+
* @since 5.2.0
777+
*/
778+
@Override
779+
public UriComponentsBuilder replaceQueryParam(String name, @Nullable Collection<?> values) {
780+
return replaceQueryParam(name, values != null ? values.toArray() : EMPTY_VALUES);
781+
}
782+
748783
/**
749784
* Set the query parameter values overriding all existing query values.
750785
* @param params the query parameter name

spring-web/src/test/java/org/springframework/web/util/UriComponentsBuilderTests.java

Lines changed: 43 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
import java.net.URI;
2020
import java.net.URISyntaxException;
2121
import java.util.Arrays;
22+
import java.util.Collection;
2223
import java.util.Collections;
2324
import java.util.HashMap;
2425
import java.util.Map;
@@ -643,9 +644,20 @@ public void replaceQuery() {
643644
}
644645

645646
@Test
646-
public void queryParams() {
647+
public void queryParam() {
648+
UriComponents result = UriComponentsBuilder.newInstance().queryParam("baz", "qux", 42).build();
649+
650+
assertThat(result.getQuery()).isEqualTo("baz=qux&baz=42");
651+
MultiValueMap<String, String> expectedQueryParams = new LinkedMultiValueMap<>(2);
652+
expectedQueryParams.add("baz", "qux");
653+
expectedQueryParams.add("baz", "42");
654+
assertThat(result.getQueryParams()).isEqualTo(expectedQueryParams);
655+
}
656+
657+
@Test
658+
public void queryParamWithList() {
647659
UriComponentsBuilder builder = UriComponentsBuilder.newInstance();
648-
UriComponents result = builder.queryParam("baz", "qux", 42).build();
660+
UriComponents result = builder.queryParam("baz", Arrays.asList("qux", 42)).build();
649661

650662
assertThat(result.getQuery()).isEqualTo("baz=qux&baz=42");
651663
MultiValueMap<String, String> expectedQueryParams = new LinkedMultiValueMap<>(2);
@@ -665,6 +677,20 @@ public void emptyQueryParam() {
665677
assertThat(result.getQueryParams()).isEqualTo(expectedQueryParams);
666678
}
667679

680+
@Test
681+
public void emptyQueryParams() {
682+
UriComponents result = UriComponentsBuilder.newInstance()
683+
.queryParam("baz", Collections.emptyList())
684+
.queryParam("foo", (Collection<?>) null)
685+
.build();
686+
687+
assertThat(result.getQuery()).isEqualTo("baz&foo");
688+
MultiValueMap<String, String> expectedQueryParams = new LinkedMultiValueMap<>(2);
689+
expectedQueryParams.add("baz", null);
690+
expectedQueryParams.add("foo", null);
691+
assertThat(result.getQueryParams()).isEqualTo(expectedQueryParams);
692+
}
693+
668694
@Test
669695
public void replaceQueryParam() {
670696
UriComponentsBuilder builder = UriComponentsBuilder.newInstance().queryParam("baz", "qux", 42);
@@ -680,6 +706,21 @@ public void replaceQueryParam() {
680706
assertThat(result.getQuery()).as("Query param should have been deleted").isNull();
681707
}
682708

709+
@Test
710+
public void replaceQueryParams() {
711+
UriComponentsBuilder builder = UriComponentsBuilder.newInstance().queryParam("baz", Arrays.asList("qux", 42));
712+
builder.replaceQueryParam("baz", Arrays.asList("xuq", 24));
713+
UriComponents result = builder.build();
714+
715+
assertThat(result.getQuery()).isEqualTo("baz=xuq&baz=24");
716+
717+
builder = UriComponentsBuilder.newInstance().queryParam("baz", Arrays.asList("qux", 42));
718+
builder.replaceQueryParam("baz", Collections.emptyList());
719+
result = builder.build();
720+
721+
assertThat(result.getQuery()).as("Query param should have been deleted").isNull();
722+
}
723+
683724
@Test
684725
public void buildAndExpandHierarchical() {
685726
UriComponents result = UriComponentsBuilder.fromPath("/{foo}").buildAndExpand("fooValue");

0 commit comments

Comments
 (0)