SPR-8803 Add UriComponentsBuilder methods to replace path/query.
This commit is contained in:
parent
8889284517
commit
d3f4c69f00
|
|
@ -21,6 +21,7 @@ Changes in version 3.1 RC2 (2011-11-15)
|
||||||
* The Form input tag allows type values other than "text" such as HTML5-specific types.
|
* The Form input tag allows type values other than "text" such as HTML5-specific types.
|
||||||
* The Form hidden tag supports "disabled" attribute
|
* The Form hidden tag supports "disabled" attribute
|
||||||
* Add ignoreDefaultModelOnRedirect attribute to <mvc:annotation-driven/>
|
* Add ignoreDefaultModelOnRedirect attribute to <mvc:annotation-driven/>
|
||||||
|
* Add methods to UriComponentsBuilder for replacing the path or the query.
|
||||||
|
|
||||||
Changes in version 3.1 RC1 (2011-10-11)
|
Changes in version 3.1 RC1 (2011-10-11)
|
||||||
---------------------------------------
|
---------------------------------------
|
||||||
|
|
|
||||||
|
|
@ -44,6 +44,7 @@ import org.springframework.util.StringUtils;
|
||||||
* </ol>
|
* </ol>
|
||||||
*
|
*
|
||||||
* @author Arjen Poutsma
|
* @author Arjen Poutsma
|
||||||
|
* @author Rossen Stoyanchev
|
||||||
* @see #newInstance()
|
* @see #newInstance()
|
||||||
* @see #fromPath(String)
|
* @see #fromPath(String)
|
||||||
* @see #fromUri(URI)
|
* @see #fromUri(URI)
|
||||||
|
|
@ -313,12 +314,25 @@ public class UriComponentsBuilder {
|
||||||
public UriComponentsBuilder path(String path) {
|
public UriComponentsBuilder path(String path) {
|
||||||
if (path != null) {
|
if (path != null) {
|
||||||
this.pathBuilder = this.pathBuilder.appendPath(path);
|
this.pathBuilder = this.pathBuilder.appendPath(path);
|
||||||
} else {
|
}
|
||||||
|
else {
|
||||||
this.pathBuilder = NULL_PATH_COMPONENT_BUILDER;
|
this.pathBuilder = NULL_PATH_COMPONENT_BUILDER;
|
||||||
}
|
}
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the path of this builder overriding all existing path and path segment values.
|
||||||
|
*
|
||||||
|
* @param path the URI path; a {@code null} value results in an empty path.
|
||||||
|
* @return this UriComponentsBuilder
|
||||||
|
*/
|
||||||
|
public UriComponentsBuilder replacePath(String path) {
|
||||||
|
this.pathBuilder = NULL_PATH_COMPONENT_BUILDER;
|
||||||
|
path(path);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Appends the given path segments to the existing path of this builder. Each given path segments may contain URI
|
* Appends the given path segments to the existing path of this builder. Each given path segments may contain URI
|
||||||
* template variables.
|
* template variables.
|
||||||
|
|
@ -335,7 +349,7 @@ public class UriComponentsBuilder {
|
||||||
/**
|
/**
|
||||||
* Appends the given query to the existing query of this builder. The given query may contain URI template variables.
|
* Appends the given query to the existing query of this builder. The given query may contain URI template variables.
|
||||||
*
|
*
|
||||||
* @param query the URI path
|
* @param query the query string
|
||||||
* @return this UriComponentsBuilder
|
* @return this UriComponentsBuilder
|
||||||
*/
|
*/
|
||||||
public UriComponentsBuilder query(String query) {
|
public UriComponentsBuilder query(String query) {
|
||||||
|
|
@ -348,11 +362,22 @@ public class UriComponentsBuilder {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
queryParams.clear();
|
this.queryParams.clear();
|
||||||
}
|
}
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the query of this builder overriding all existing query parameters.
|
||||||
|
*
|
||||||
|
* @param query the query string; a {@code null} value removes all query parameters.
|
||||||
|
* @return this UriComponentsBuilder
|
||||||
|
*/
|
||||||
|
public UriComponentsBuilder replaceQuery(String query) {
|
||||||
|
this.queryParams.clear();
|
||||||
|
query(query);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Appends the given query parameter to the existing query parameters. The given name or any of the values may contain
|
* Appends the given query parameter to the existing query parameters. The given name or any of the values may contain
|
||||||
|
|
@ -368,15 +393,30 @@ public class UriComponentsBuilder {
|
||||||
if (!ObjectUtils.isEmpty(values)) {
|
if (!ObjectUtils.isEmpty(values)) {
|
||||||
for (Object value : values) {
|
for (Object value : values) {
|
||||||
String valueAsString = value != null ? value.toString() : null;
|
String valueAsString = value != null ? value.toString() : null;
|
||||||
queryParams.add(name, valueAsString);
|
this.queryParams.add(name, valueAsString);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
queryParams.add(name, null);
|
this.queryParams.add(name, null);
|
||||||
}
|
}
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the query parameter values overriding all existing query values for the same parameter.
|
||||||
|
* If no values are given, the resulting URI will contain the query parameter name only.
|
||||||
|
*
|
||||||
|
* @param name the query parameter name
|
||||||
|
* @param values the query parameter values
|
||||||
|
* @return this UriComponentsBuilder
|
||||||
|
*/
|
||||||
|
public UriComponentsBuilder replaceQueryParam(String name, Object... values) {
|
||||||
|
Assert.notNull(name, "'name' must not be null");
|
||||||
|
this.queryParams.remove(name);
|
||||||
|
queryParam(name, values);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the URI fragment. The given fragment may contain URI template variables, and may also be {@code null} to clear
|
* Sets the URI fragment. The given fragment may contain URI template variables, and may also be {@code null} to clear
|
||||||
* the fragment of this builder.
|
* the fragment of this builder.
|
||||||
|
|
|
||||||
|
|
@ -174,6 +174,36 @@ public class UriComponentsBuilderTests {
|
||||||
assertEquals(Arrays.asList("foo"), result.getPathSegments());
|
assertEquals(Arrays.asList("foo"), result.getPathSegments());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void replacePath() {
|
||||||
|
UriComponentsBuilder builder = UriComponentsBuilder.fromUriString("http://www.ietf.org/rfc/rfc2396.txt");
|
||||||
|
builder.replacePath("/rfc/rfc3986.txt");
|
||||||
|
UriComponents result = builder.build();
|
||||||
|
|
||||||
|
assertEquals("http://www.ietf.org/rfc/rfc3986.txt", result.toUriString());
|
||||||
|
|
||||||
|
builder = UriComponentsBuilder.fromUriString("http://www.ietf.org/rfc/rfc2396.txt");
|
||||||
|
builder.replacePath(null);
|
||||||
|
result = builder.build();
|
||||||
|
|
||||||
|
assertEquals("http://www.ietf.org", result.toUriString());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void replaceQuery() {
|
||||||
|
UriComponentsBuilder builder = UriComponentsBuilder.fromUriString("http://example.com/foo?foo=bar&baz=qux");
|
||||||
|
builder.replaceQuery("baz=42");
|
||||||
|
UriComponents result = builder.build();
|
||||||
|
|
||||||
|
assertEquals("http://example.com/foo?baz=42", result.toUriString());
|
||||||
|
|
||||||
|
builder = UriComponentsBuilder.fromUriString("http://example.com/foo?foo=bar&baz=qux");
|
||||||
|
builder.replaceQuery(null);
|
||||||
|
result = builder.build();
|
||||||
|
|
||||||
|
assertEquals("http://example.com/foo", result.toUriString());
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void queryParams() throws URISyntaxException {
|
public void queryParams() throws URISyntaxException {
|
||||||
UriComponentsBuilder builder = UriComponentsBuilder.newInstance();
|
UriComponentsBuilder builder = UriComponentsBuilder.newInstance();
|
||||||
|
|
@ -197,4 +227,20 @@ public class UriComponentsBuilderTests {
|
||||||
assertEquals(expectedQueryParams, result.getQueryParams());
|
assertEquals(expectedQueryParams, result.getQueryParams());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void replaceQueryParam() {
|
||||||
|
UriComponentsBuilder builder = UriComponentsBuilder.newInstance().queryParam("baz", "qux", 42);
|
||||||
|
builder.replaceQueryParam("baz", "xuq", 24);
|
||||||
|
UriComponents result = builder.build();
|
||||||
|
|
||||||
|
assertEquals("baz=xuq&baz=24", result.getQuery());
|
||||||
|
|
||||||
|
builder = UriComponentsBuilder.newInstance().queryParam("baz", "qux", 42);
|
||||||
|
builder.replaceQueryParam("baz");
|
||||||
|
result = builder.build();
|
||||||
|
|
||||||
|
assertEquals("baz", result.getQuery());
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1792,7 +1792,9 @@ public class EditPetForm {
|
||||||
so no attributes should be passed on to
|
so no attributes should be passed on to
|
||||||
<classname>RedirectView</classname>. Both the MVC namespace and the
|
<classname>RedirectView</classname>. Both the MVC namespace and the
|
||||||
MVC Java config (via <interfacename>@EnableWebMvc</interfacename>)
|
MVC Java config (via <interfacename>@EnableWebMvc</interfacename>)
|
||||||
automatically set this flag to <literal>true</literal>.</para>
|
keep this flag set to <literal>false</literal> in order to maintain
|
||||||
|
backwards compatibility. However, for new applications we recommend
|
||||||
|
setting it to <literal>true</literal></para>
|
||||||
|
|
||||||
<para>The <interfacename>RedirectAttributes</interfacename> interface
|
<para>The <interfacename>RedirectAttributes</interfacename> interface
|
||||||
can also be used to add flash attributes. Unlike other redirect
|
can also be used to add flash attributes. Unlike other redirect
|
||||||
|
|
|
||||||
|
|
@ -467,5 +467,25 @@
|
||||||
linkend="mvc-multipart-forms-non-browsers" /> and <xref
|
linkend="mvc-multipart-forms-non-browsers" /> and <xref
|
||||||
linkend="mvc-multipart" />.</para>
|
linkend="mvc-multipart" />.</para>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
|
<section>
|
||||||
|
<title><classname>UriComponentsBuilder</classname> and <classname>UriComponents</classname></title>
|
||||||
|
|
||||||
|
<para>A new <classname>UriComponents</classname> class has been added,
|
||||||
|
which is an immutable container of URI components providing
|
||||||
|
access to all contained URI components.
|
||||||
|
A nenw <classname>UriComponentsBuilder</classname> class is also
|
||||||
|
provided to help create <classname>UriComponents</classname> instances.
|
||||||
|
Together the two classes give fine-grained control over all
|
||||||
|
aspects of preparing a URI including construction, expansion
|
||||||
|
from URI template variables, and encoding.</para>
|
||||||
|
|
||||||
|
<para>In most cases the new classes can be used as a more flexible
|
||||||
|
alternative to the existing <classname>UriTemplate</classname>
|
||||||
|
especially since <classname>UriTemplate</classname> relies on those
|
||||||
|
same classes internally.
|
||||||
|
</para>
|
||||||
|
</section>
|
||||||
|
|
||||||
</section>
|
</section>
|
||||||
</chapter>
|
</chapter>
|
||||||
|
|
|
||||||
|
|
@ -1434,6 +1434,56 @@ URI location = template.postForLocation(uri, booking, "1");
|
||||||
information on using the execute method and the meaning of its other
|
information on using the execute method and the meaning of its other
|
||||||
method arguments.</para>
|
method arguments.</para>
|
||||||
|
|
||||||
|
<section>
|
||||||
|
<title>Working with the URI</title>
|
||||||
|
|
||||||
|
<para>For each of the main HTTP methods, the <classname>RestTemplate</classname>
|
||||||
|
provides variants that either take a String URI or <classname>java.net.URI</classname>
|
||||||
|
as the first argument.
|
||||||
|
</para>
|
||||||
|
|
||||||
|
<para>The String URI variants accept template arguments as a
|
||||||
|
String variable length argument or as a <classname>Map<String,String></classname>.
|
||||||
|
They also assume the URL String is not encoded and needs to be encoded.
|
||||||
|
For example the following:
|
||||||
|
</para>
|
||||||
|
|
||||||
|
<programlisting language="java">restTemplate.getForObject("http://example.com/hotel list", String.class);</programlisting>
|
||||||
|
|
||||||
|
<para>will perform a GET on <filename>http://example.com/hotel%20list</filename>.
|
||||||
|
That means if the input URL String is already encoded, it will be encoded twice --
|
||||||
|
i.e. <filename>http://example.com/hotel%20list</filename> will become
|
||||||
|
<filename>http://example.com/hotel%2520list</filename>.
|
||||||
|
If this is not the intended effect, use the
|
||||||
|
<classname>java.net.URI</classname> method variant, which assumes
|
||||||
|
the URL is already encoded is also generally useful if you want
|
||||||
|
to reuse a single (fully expanded) <classname>URI</classname>
|
||||||
|
multiple times.</para>
|
||||||
|
|
||||||
|
<para>The <classname>UriComponentsBuilder</classname> class can be used
|
||||||
|
to build and encode the <classname>URI</classname> including support
|
||||||
|
for URI templates. For example you can start with a URL String:
|
||||||
|
</para>
|
||||||
|
|
||||||
|
<programlisting language="java">UriComponents uriComponents =
|
||||||
|
UriComponentsBuilder.fromUriString("http://example.com/hotels/{hotel}/bookings/{booking}").build()
|
||||||
|
.expand("42", "21")
|
||||||
|
.encode();
|
||||||
|
|
||||||
|
URI uri = uriComponents.toUri();</programlisting>
|
||||||
|
|
||||||
|
<para>Or specify each URI component indiviudally:</para>
|
||||||
|
|
||||||
|
<programlisting language="java">UriComponents uriComponents =
|
||||||
|
UriComponentsBuilder.newInstance()
|
||||||
|
.scheme("http").host("example.com").path("/hotels/{hotel}/bookings/{booking}").build()
|
||||||
|
.expand("42", "21")
|
||||||
|
.encode();
|
||||||
|
|
||||||
|
URI uri = uriComponents.toUri();</programlisting>
|
||||||
|
|
||||||
|
</section>
|
||||||
|
|
||||||
<section>
|
<section>
|
||||||
<title>Dealing with request and response headers</title>
|
<title>Dealing with request and response headers</title>
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue