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-17 09:11:36 +08:00
|
|
|
When using `UriComponentsBuilder` directly, this is the preferred way to encode:
|
2018-02-16 12:25:52 +08:00
|
|
|
|
2018-07-17 09:11:36 +08:00
|
|
|
[source,java,indent=0]
|
|
|
|
[subs="verbatim,quotes"]
|
|
|
|
----
|
|
|
|
String uriTemplate = "http://example.com/hotels/{hotel}";
|
|
|
|
|
|
|
|
URI uri = UriComponentsBuilder.fromUriString(uriTemplate)
|
|
|
|
.queryParam("q", "{q}")
|
|
|
|
.encode()
|
|
|
|
.buildAndexpand("Westin", "123")
|
|
|
|
.toUri();
|
|
|
|
----
|
2018-02-16 12:25:52 +08:00
|
|
|
|
2018-07-17 09:11:36 +08:00
|
|
|
First, the URI template is encoded when `UriComponents` is built. Then URI variables are
|
|
|
|
encoded separately when expanded. The following rules apply to each:
|
2018-02-16 12:25:52 +08:00
|
|
|
|
2018-07-17 09:11:36 +08:00
|
|
|
* The URI template is encoded by quoting _only_ characters that are illegal within a
|
|
|
|
given URI component type. For example, spaces are illegal in a path and therefore encoded.
|
|
|
|
* URI variables are encoded more strictly, by quoting both illegal characters and also
|
|
|
|
characters with reserved meaning. For example ";" is legal in a path but has reserved
|
|
|
|
meaning (as a path parameter separator) and therefore encoded.
|
2018-02-16 12:25:52 +08:00
|
|
|
|
2018-07-17 09:11:36 +08:00
|
|
|
The `WebClient` and the `RestTemplate` rely on a `UriBuilderFactory` to expand URI template
|
|
|
|
and apply encoding. The `DefaultUriBuilderFactory` provides multiple encoding modes:
|
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;
|
|
|
|
|
2018-02-16 12:25:52 +08:00
|
|
|
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
|
|
|
|
|
|
|
RestTemplate restTemplate = new RestTemplate();
|
|
|
|
restTemplate.setUriTemplateHandler(factory);
|
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-17 09:11:36 +08:00
|
|
|
Internally `DefaultUriBuilderFactory` uses `UriComponentsBuilder`. The
|
|
|
|
`EncodingMode.TEMPLATE_AND_VALUES` corresponds to the `UriComponentsBuilder` encoding
|
|
|
|
example shown earlier. It is the preferred mode.
|
|
|
|
|
|
|
|
Out of the box, `RestTemplate` is configured with `EncodingMode.URI_COMPONENTS` which has
|
|
|
|
been used historically and still is the default for backwards compatibility. It works by
|
|
|
|
expanding URI variables first, and then encoding the expanded URI component values,
|
|
|
|
quoting _only_ illegal characters within a given URI component type, but not all
|
|
|
|
characters with reserved meaning. As of 5.0.8, you can switch to the preferred
|
|
|
|
`EncodingMode.TEMPLATE_AND_VALUES`.
|
2018-02-16 12:25:52 +08:00
|
|
|
|
2018-07-17 09:11:36 +08:00
|
|
|
`WebClient` is configured with `EncodingMode.TEMPLATE_AND_VALUES` by default starting in
|
|
|
|
5.1, In 5.0.x however the default remains `EncodingMode.URI_COMPONENTS`.
|