2018-02-16 12:25:52 +08:00
|
|
|
|
|
|
|
[[web-uricomponents]]
|
|
|
|
= UriComponents
|
2018-02-17 01:58:01 +08:00
|
|
|
[.small]#Spring MVC and Spring WebFlux#
|
2018-02-16 12:25:52 +08:00
|
|
|
|
2018-07-17 09:11:36 +08:00
|
|
|
`UriComponentsBuilder` helps to build URI's from URI templates with variables:
|
2018-02-16 12:25:52 +08:00
|
|
|
|
|
|
|
[source,java,indent=0]
|
|
|
|
[subs="verbatim,quotes"]
|
|
|
|
----
|
|
|
|
String uriTemplate = "http://example.com/hotels/{hotel}";
|
|
|
|
|
|
|
|
UriComponents uriComponents = UriComponentsBuilder.fromUriString(uriTemplate) // <1>
|
|
|
|
.queryParam("q", "{q}") // <2>
|
2018-07-17 09:11:36 +08:00
|
|
|
.encode() // <3>
|
|
|
|
.build(); // <4>
|
2018-02-16 12:25:52 +08:00
|
|
|
|
2018-07-17 09:11:36 +08:00
|
|
|
URI uri = uriComponents.expand("Westin", "123").toUri(); // <5>
|
2018-02-16 12:25:52 +08:00
|
|
|
----
|
|
|
|
<1> Static factory method with a URI template.
|
2018-07-17 09:11:36 +08:00
|
|
|
<2> Add and/or replace URI components.
|
|
|
|
<3> Request to have the URI template and URI variables encoded.
|
|
|
|
<4> Build a `UriComponents`.
|
|
|
|
<5> Expand variables, and obtain the `URI`.
|
2018-02-16 12:25:52 +08:00
|
|
|
|
2018-07-17 09:11:36 +08:00
|
|
|
The above can also be done in shorthand form:
|
2018-02-16 12:25:52 +08:00
|
|
|
|
|
|
|
[source,java,indent=0]
|
|
|
|
[subs="verbatim,quotes"]
|
|
|
|
----
|
|
|
|
URI uri = UriComponentsBuilder.fromUriString(uriTemplate)
|
|
|
|
.queryParam("q", "{q}")
|
|
|
|
.encode()
|
2018-07-17 09:11:36 +08:00
|
|
|
.buildAndExpand("Westin", "123")
|
2018-02-16 12:25:52 +08:00
|
|
|
.toUri();
|
|
|
|
----
|
|
|
|
|
|
|
|
|
|
|
|
[[web-uribuilder]]
|
|
|
|
= UriBuilder
|
2018-02-17 01:58:01 +08:00
|
|
|
[.small]#Spring MVC and Spring WebFlux#
|
2018-02-16 12:25:52 +08:00
|
|
|
|
2018-07-17 09:11:36 +08:00
|
|
|
<<web-uricomponents,UriComponentsBuilder>> implements `UriBuilder`. A `UriBuilder` in turn
|
|
|
|
can be created with a `UriBuilderFactory`. Together `UriBuilderFactory` and `UriBuilder`
|
|
|
|
provide a pluggable mechanism to build URIs from URI templates, based on shared
|
|
|
|
configuration such as a base url, encoding preferences, and others.
|
2018-02-16 12:25:52 +08:00
|
|
|
|
2018-07-17 09:11:36 +08:00
|
|
|
The `RestTemplate` and the `WebClient` can be configured with a `UriBuilderFactory`
|
|
|
|
to customize the preparation of URIs. `DefaultUriBuilderFactory` is a default
|
|
|
|
implementation of `UriBuilderFactory` that uses `UriComponentsBuilder` internally and
|
|
|
|
exposes shared configuration options.
|
2018-02-16 12:25:52 +08:00
|
|
|
|
2018-07-17 09:11:36 +08:00
|
|
|
`RestTemplate` example:
|
2018-02-16 12:25:52 +08:00
|
|
|
|
|
|
|
[source,java,indent=0]
|
|
|
|
[subs="verbatim,quotes"]
|
|
|
|
----
|
2018-07-17 09:11:36 +08:00
|
|
|
// import org.springframework.web.util.DefaultUriBuilderFactory.EncodingMode;
|
|
|
|
|
|
|
|
String baseUrl = "http://example.org";
|
2018-02-16 12:25:52 +08:00
|
|
|
DefaultUriBuilderFactory factory = new DefaultUriBuilderFactory(baseUrl);
|
2018-07-17 09:11:36 +08:00
|
|
|
factory.setEncodingMode(EncodingMode.TEMPLATE_AND_VARIABLES);
|
2018-02-16 12:25:52 +08:00
|
|
|
|
|
|
|
RestTemplate restTemplate = new RestTemplate();
|
|
|
|
restTemplate.setUriTemplateHandler(factory);
|
|
|
|
----
|
|
|
|
|
2018-07-17 09:11:36 +08:00
|
|
|
`WebClient` example:
|
2018-02-16 12:25:52 +08:00
|
|
|
|
|
|
|
[source,java,indent=0]
|
|
|
|
[subs="verbatim,quotes"]
|
|
|
|
----
|
2018-07-17 09:11:36 +08:00
|
|
|
// import org.springframework.web.util.DefaultUriBuilderFactory.EncodingMode;
|
|
|
|
|
|
|
|
String baseUrl = "http://example.org";
|
2018-02-16 12:25:52 +08:00
|
|
|
DefaultUriBuilderFactory factory = new DefaultUriBuilderFactory(baseUrl);
|
2018-07-17 09:11:36 +08:00
|
|
|
factory.setEncodingMode(EncodingMode.TEMPLATE_AND_VARIABLES);
|
2018-02-16 12:25:52 +08:00
|
|
|
|
|
|
|
WebClient client = WebClient.builder().uriBuilderFactory(factory).build();
|
|
|
|
----
|
|
|
|
|
2018-07-17 09:11:36 +08:00
|
|
|
In addition `DefaultUriBuilderFactory` can also be used directly. It is similar to using
|
|
|
|
`UriComponentsBuilder` but instead of static factory methods, it is an actual instance
|
|
|
|
that holds configuration and preferences:
|
2018-02-16 12:25:52 +08:00
|
|
|
|
|
|
|
[source,java,indent=0]
|
|
|
|
[subs="verbatim,quotes"]
|
|
|
|
----
|
|
|
|
String baseUrl = "http://example.com";
|
|
|
|
DefaultUriBuilderFactory uriBuilderFactory = new DefaultUriBuilderFactory(baseUrl);
|
|
|
|
|
|
|
|
URI uri = uriBuilderFactory.uriString("/hotels/{hotel}")
|
|
|
|
.queryParam("q", "{q}")
|
2018-07-17 09:11:36 +08:00
|
|
|
.build("Westin", "123");
|
2018-02-16 12:25:52 +08:00
|
|
|
----
|
|
|
|
|
|
|
|
|
|
|
|
[[web-uri-encoding]]
|
|
|
|
= URI Encoding
|
2018-02-17 01:58:01 +08:00
|
|
|
[.small]#Spring MVC and Spring WebFlux#
|
2018-02-16 12:25:52 +08:00
|
|
|
|
2018-07-18 03:58:15 +08:00
|
|
|
`UriComponentsBuilder` exposes encoding options at 2 levels:
|
|
|
|
|
|
|
|
. {api-spring-framework}/web/util/UriComponentsBuilder.html#encode--[UriComponentsBuilder#encode()] -
|
|
|
|
pre-encodes the URI template first, then strictly encodes URI variables when expanded.
|
|
|
|
. {api-spring-framework}/web/util/UriComponents.html#encode--[UriComponents#encode()] -
|
|
|
|
encodes URI components _after_ URI variables are expanded.
|
|
|
|
|
|
|
|
Both options replace non-ASCII and illegal characters with escaped octets, however option
|
|
|
|
1 also replaces characters with reserved meaning that appear in URI variables.
|
|
|
|
|
|
|
|
[TIP]
|
|
|
|
====
|
|
|
|
Consider ";" which is legal in a path but has reserved meaning. Option 1 replaces
|
|
|
|
";" with "%3B" in URI variables but not in the URI template. By contrast, option 2 never
|
|
|
|
replaces ";" since it is a legal character in a path.
|
|
|
|
====
|
|
|
|
|
2018-07-18 04:40:52 +08:00
|
|
|
For most cases option 1 is likely to give the expected result because it treats URI
|
2018-07-18 03:58:15 +08:00
|
|
|
variables as opaque data to be fully encoded, while option 2 is useful only if
|
2018-07-18 04:40:52 +08:00
|
|
|
URI variables intentionally contain reserved characters.
|
2018-07-18 03:58:15 +08:00
|
|
|
|
|
|
|
Example usage using option 1:
|
2018-02-16 12:25:52 +08:00
|
|
|
|
2018-07-17 09:11:36 +08:00
|
|
|
[source,java,indent=0]
|
|
|
|
[subs="verbatim,quotes"]
|
|
|
|
----
|
2018-07-18 03:58:15 +08:00
|
|
|
UriComponentsBuilder.fromPath("/hotel list/{city}")
|
2018-07-17 09:11:36 +08:00
|
|
|
.queryParam("q", "{q}")
|
|
|
|
.encode()
|
2018-07-18 03:58:15 +08:00
|
|
|
.buildAndexpand("New York", "foo+bar")
|
|
|
|
.toUriString();
|
2018-02-16 12:25:52 +08:00
|
|
|
|
2018-07-18 03:58:15 +08:00
|
|
|
// Result is "/hotel%20list/New%20York?foo%2Bbar"
|
|
|
|
----
|
2018-02-16 12:25:52 +08:00
|
|
|
|
2018-07-18 03:58:15 +08:00
|
|
|
The `WebClient` and the `RestTemplate` expand and encode URI templates internally through
|
2018-07-18 04:40:52 +08:00
|
|
|
the `UriBuilderFactory` strategy. Both can be configured with a custom strategy:
|
2018-02-16 12:25:52 +08:00
|
|
|
|
|
|
|
[source,java,indent=0]
|
|
|
|
[subs="verbatim,quotes"]
|
|
|
|
----
|
|
|
|
String baseUrl = "http://example.com";
|
|
|
|
DefaultUriBuilderFactory factory = new DefaultUriBuilderFactory(baseUrl)
|
2018-07-17 09:11:36 +08:00
|
|
|
factory.setEncodingMode(EncodingMode.TEMPLATE_AND_VALUES);
|
2018-06-12 22:14:35 +08:00
|
|
|
|
2018-07-18 04:40:52 +08:00
|
|
|
// Customize the RestTemplate..
|
2018-06-12 22:14:35 +08:00
|
|
|
RestTemplate restTemplate = new RestTemplate();
|
|
|
|
restTemplate.setUriTemplateHandler(factory);
|
2018-07-17 09:11:36 +08:00
|
|
|
|
2018-07-18 04:40:52 +08:00
|
|
|
// Customize the WebClient..
|
2018-07-17 09:11:36 +08:00
|
|
|
WebClient client = WebClient.builder().uriBuilderFactory(factory).build();
|
2018-02-16 12:25:52 +08:00
|
|
|
----
|
|
|
|
|
2018-07-18 04:40:52 +08:00
|
|
|
The `DefaultUriBuilderFactory` implementation uses `UriComponentsBuilder` internally to
|
|
|
|
expand and encode URI templates. As a factory it provides a single place to configure
|
|
|
|
the approach to encoding based on one of the below encoding modes:
|
2018-07-17 09:11:36 +08:00
|
|
|
|
2018-07-18 04:40:52 +08:00
|
|
|
* `TEMPLATE_AND_VALUES` -- uses `UriComponentsBuilder#encode()`, corresponding to
|
|
|
|
option 1 above, to pre-encode the URI template and strictly encode URI variables when
|
|
|
|
expanded.
|
|
|
|
* `VALUES_ONLY` -- does not encode the URI template and instead applies strict encoding
|
|
|
|
to URI variables via `UriUtils#encodeUriUriVariables` prior to expanding them into the
|
|
|
|
template.
|
2018-07-18 03:58:15 +08:00
|
|
|
* `URI_COMPONENTS` -- uses `UriComponents#encode()`, corresponding to option 2 above, to
|
|
|
|
encode URI component value _after_ URI variables are expanded.
|
|
|
|
* `NONE` -- no encoding is applied.
|
2018-02-16 12:25:52 +08:00
|
|
|
|
2018-07-18 04:40:52 +08:00
|
|
|
Out of the box the `RestTemplate` is set to `EncodingMode.URI_COMPONENTS` for historic
|
|
|
|
reasons and for backwards compatibility. The `WebClient` relies on the default value
|
|
|
|
in `DefaultUriBuilderFactory` which was changed from `EncodingMode.URI_COMPONENTS` in
|
|
|
|
5.0.x to `EncodingMode.TEMPLATE_AND_VALUES` in 5.1.
|