UriComponents

UriComponentsBuilder helps you create URIs from URI templates with variables, as shown in the following example:

Java

UriComponents uriComponents = UriComponentsBuilder
.fromUriString("https://example.com/hotels/{hotel}") 
.queryParam("q", "{q}") 
.encode() 
.build(); 
URI uri = uriComponents.expand("Westin", "123").toUri();
        
  1. Static factory method with URI template.
  2. Add or replace URI components.
  3. Request to encode a URI template and URI variables.
  4. Collect UriComponents .
  5. Expand the variables and get URI.
Kotlin

val uriComponents = UriComponentsBuilder
.fromUriString("https://example.com/hotels/{hotel}") 
.queryParam("q", "{q}") 
.encode() 
.build() 
val uri = uriComponents.expand("Westin", "123").toUri()
  1. Static factory method with URI template.
  2. Add or replace URI components.
  3. Request to encode a URI template and URI variables.
  4. Collect UriComponents.
  5. We expand the variables and get URI.

The code from the previous example can be combined into one chain and shortened using buildAndExpand, as shown in the following example:

Java

URI uri = UriComponentsBuilder
.fromUriString("https://example.com/hotels/{hotel}")
.queryParam("q", "{q}")
.encode()
.buildAndExpand("Westin", "123")
.toUri();
Kotlin

val uri = UriComponentsBuilder
.fromUriString("https://example.com/hotels/{hotel}")
.queryParam("q", "{q}")
.encode()
.buildAndExpand("Westin", "123")
.toUri()

You can shorten it even further by going directly to the URI (which implies an encoding), as shown in the following example:

Java

URI uri = UriComponentsBuilder
.fromUriString("https://example.com/hotels/{hotel}")
.queryParam("q", "{q}")
.build("Westin", "123");
Kotlin

val uri = UriComponentsBuilder
.fromUriString("https://example.com/hotels/{hotel}")
.queryParam("q", "{q}")
.build("Westin", "123");

You can shorten it even further using the full Template URI, as shown in the following example:

Java

URI uri = UriComponentsBuilder
.fromUriString("https://example.com/hotels/{hotel}?q={q}")
.build("Westin", "123");
Kotlin

val uri = UriComponentsBuilder
.fromUriString("https://example.com/hotels/{hotel}?q={q}")
.build("Westin", "123")

UriBuilder

UriComponentsBuilder implements UriBuilder. In turn, you can create a UriBuilder using UriBuilderFactory. Together, UriBuilderFactory and UriBuilder provide a plug-in mechanism for generating URIs from URI templates based on common configuration, such as the base URL, encoding options, and other details.

You can configure RestTemplate and WebClient using UriBuilderFactory to configure URI preparation. DefaultUriBuilderFactory is a default implementation of UriBuilderFactory that uses UriComponentsBuilder internally and exposes general configuration options.

In the following The example shows how to configure such a bean:

Java

// import org.springframework.web.util.DefaultUriBuilderFactory.EncodingMode;
String baseUrl = "https://example.org";
DefaultUriBuilderFactory factory = new DefaultUriBuilderFactory(baseUrl);
factory.setEncodingMode(EncodingMode.TEMPLATE_AND_VALUES);
RestTemplate restTemplate = new RestTemplate();
restTemplate.setUriTemplateHandler(factory);
Kotlin

// import org.springframework.web.util.DefaultUriBuilderFactory.EncodingMode
val baseUrl = "https://example.org"
val factory = DefaultUriBuilderFactory(baseUrl)
factory.encodingMode = EncodingMode.TEMPLATE_AND_VALUES
val restTemplate = RestTemplate()
restTemplate.uriTemplateHandler = factory

The following example configures a WebClient:

Java

// import org.springframework.web.util.DefaultUriBuilderFactory.EncodingMode;
String baseUrl = "https://example.org";
DefaultUriBuilderFactory factory = new DefaultUriBuilderFactory(baseUrl);
factory.setEncodingMode(EncodingMode.TEMPLATE_AND_VALUES);
WebClient client = WebClient.builder().uriBuilderFactory(factory).build();
Kotlin

// import org.springframework.web.util.DefaultUriBuilderFactory.EncodingMode
val baseUrl = "https://example.org"
val factory = DefaultUriBuilderFactory(baseUrl)
factory.encodingMode = EncodingMode.TEMPLATE_AND_VALUES
val client = WebClient.builder().uriBuilderFactory(factory).build()

Also, you can use DefaultUriBuilderFactory directly. This is similar to using UriComponentsBuilder, but instead of static factory methods, it is an actual instance that stores configuration and parameters, as shown in the following example:

Java

String baseUrl = "https://example.com";
DefaultUriBuilderFactory uriBuilderFactory = new DefaultUriBuilderFactory(baseUrl);
URI uri = uriBuilderFactory.uriString("/hotels/{hotel}")
.queryParam("q", "{q}")
.build("Westin", "123");
Kotlin

val baseUrl = "https://example.com"
val uriBuilderFactory = DefaultUriBuilderFactory(baseUrl)
val uri = uriBuilderFactory.uriString("/hotels/{hotel}")
.queryParam("q", "{q}")
.build("Westin", "123")

URI encoding

UriComponentsBuilder opens encoding options at two levels:

Both options replace non-ASCII and invalid characters with escaped octets. However, the first option also replaces characters with a reserved meaning that appear in variables.

Consider ";" which is valid in a path but has a reserved meaning . The first option replaces ";" to "%3B" in variables, but not in the URI template. In contrast, the second option never replaces ";" because it is a valid character in the path.

In most cases, the first option will most likely produce the expected result because it treats URI variables as opaque data that must be fully encoded, while the second option is useful if URI variables intentionally contain reserved characters. The second option also works if you don't expand URI variables at all, because then anything that happens to look like a URI variable is encoded.

The following example uses the first option:

Java

URI uri = UriComponentsBuilder.fromPath("/hotel list/{city}")
.queryParam("q", "{q}")
.encode()
.buildAndExpand("New York", "foo+bar")
.toUri();
// Result "/hotel%20list/New%20York?q=foo%2Bbar"
Kotlin

val uri = UriComponentsBuilder.fromPath("/hotel list/{city}")
.queryParam("q", "{q}")
.encode()
.buildAndExpand("New York", "foo+bar")
.toUri()
// Result "/hotel%20list/New%20York?q=foo%2Bbar"

You can shorten the code in the previous example by going directly to the URI (which implies an encoding), as shown in the following example:

Java

URI uri = UriComponentsBuilder.fromPath("/hotel list/{city}")
.queryParam("q", "{q}")
.build("New York", "foo+bar");
Kotlin

val uri = UriComponentsBuilder.fromPath("/hotel list/{city}")
.queryParam("q", "{q}")
.build("New York", "foo+bar")

You can shorten it even further using the full URI template, as shown in the following example:

Java

URI uri = UriComponentsBuilder.fromUriString("/hotel list/{city}?q={q}")
.build("New York", "foo+bar");
Kotlin

val uri = UriComponentsBuilder.fromUriString("/hotel list/{city}?q={q}")
.build("New York", "foo+bar")

WebClient and RestTemplate extend and encode URI templates internally using the UriBuilderFactory strategy. Both options can be configured using a custom strategy, as shown in the following example:

Java

String baseUrl = "https://example.com";
DefaultUriBuilderFactory factory = new DefaultUriBuilderFactory(baseUrl)
factory.setEncodingMode(EncodingMode.TEMPLATE_AND_VALUES);
// Configuring RestTemplate...
RestTemplate restTemplate = new RestTemplate();
restTemplate.setUriTemplateHandler(factory);
// Configuring WebClient...
WebClient client = WebClient.builder().uriBuilderFactory(factory).build();
Kotlin

val baseUrl = "https://example.com"
val factory = DefaultUriBuilderFactory(baseUrl).apply {
encodingMode = EncodingMode.TEMPLATE_AND_VALUES
}
Set up RestTemplate...
val restTemplate = RestTemplate().apply {
uriTemplateHandler = factory
}
// Setting up WebClient...
val client = WebClient.builder().uriBuilderFactory(factory).build()

The DefaultUriBuilderFactory implementation uses UriComponentsBuilder internally to extend and encode URI patterns. As a factory, it provides a single place to configure the encoding approach , based on one of the following encoding modes:

  • TEMPLATE_AND_VALUES: Uses UriComponentsBuilder#encode () corresponding to the first option in previous list, to pre-encode the URI pattern and strictly encode variables when expanding.

  • VALUES_ONLY: Does not encode the URI pattern and instead applies strictly encode URIs to variables via UriUtils#encodeUriVariables before expanding them into a template.

  • URI_COMPONENT: Uses UriComponents#encode(), corresponding to the second option in the previous list, to encode the value of a URI component after expanding URI variables.

  • NONE No encoding is applied.

RestTemplate is set to EncodingMode.URI_COMPONENT for historical reasons and for backward compatibility. WebClient accesses the default value in DefaultUriBuilderFactory, which was changed from EncodingMode.URI_COMPONENT in 5.0.x to EncodingMode.TEMPLATE_AND_VALUES in 5.1.