Componentes Uri

UriComponentsBuilder le ayuda a crear URI a partir de plantillas de URI con variables, como se muestra en el siguiente ejemplo:

Java
UriComponents uriComponents = UriComponentsBuilder
.fromUriString("https://example.com/hotels/{hotel}")
.queryParam("q", "{q}")
.encode()
.build();
URI uri = uriComponents.expand("Westin", "123").toUri();
  1. Método de fábrica estático con plantilla URI.
  2. Agregar o reemplazar componentes URI.
  3. Solicitar codificar una plantilla de URI y variables de URI.
  4. Recopilar UriComponents .
  5. Expande las variables y obtén URI.
Kotlin
val uriComponents = UriComponentsBuilder
.fromUriString("https://example.com/hotels/{hotel}")
.queryParam("q", "{q}")
.encode()
.build()
val uri = uriComponents.expand("Westin", "123").toUri()
  1. Método de fábrica estático con plantilla URI.
  2. Agregar o reemplazar componentes URI.
  3. Solicitar codificar una plantilla de URI y variables de URI.
  4. Recopilar UriComponents.
  5. Ampliamos las variables y obtenemos URI.

El código del ejemplo anterior se puede combinar en una cadena y acortar usando buildAndExpand, como se muestra en el siguiente ejemplo:

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()

Puedes acortarlo aún más yendo directamente al URI (lo que implica una codificación), como se muestra en el siguiente ejemplo:

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");

Puedes acortarlo incluso utilizando aún más el URI de plantilla completo, como se muestra en el siguiente ejemplo:

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 implementa UriBuilder. A su vez, puedes crear un UriBuilder usando UriBuilderFactory. Juntos, UriBuilderFactory y UriBuilder proporcionan un mecanismo de complemento para generar URI a partir de plantillas de URI basadas en una configuración común, como la URL base, las opciones de codificación y otros detalles.

Puede configurar RestTemplate y WebClient usando UriBuilderFactory para configurar la preparación de URI. DefaultUriBuilderFactory es una implementación predeterminada de UriBuilderFactory que utiliza UriComponentsBuilder internamente y expone opciones de configuración generales.

En el siguiente ejemplo muestra cómo configurar dicho 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

El siguiente ejemplo configura un 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()

Además, puede utilice DefaultUriBuilderFactory directamente. Esto es similar al uso de UriComponentsBuilder, pero en lugar de métodos de fábrica estáticos, es una instancia real que almacena la configuración y los parámetros, como se muestra en el siguiente ejemplo:

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")

Codificación URI

UriComponentsBuilder abre opciones de codificación en dos niveles:

Ambas opciones reemplazan caracteres no ASCII y no válidos con octetos de escape. Sin embargo, la primera opción también reemplaza caracteres con un significado reservado que aparecen en las variables.

Considere ";", que es válido en una ruta pero tiene una significado reservado. La primera opción reemplaza ";" a "%3B" en variables, pero no en la plantilla de URI. Por el contrario, la segunda opción nunca reemplaza ";" porque es un carácter válido en la ruta.

En la mayoría de los casos, la primera opción probablemente producirá el resultado esperado porque trata las variables URI como datos opacos. que debe estar completamente codificado, mientras que la segunda opción es útil si las variables URI contienen intencionalmente caracteres reservados. La segunda opción también funciona si no expandes las variables URI en absoluto, porque entonces cualquier cosa que parezca una variable URI está codificada.

El siguiente ejemplo utiliza la primera opción:

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"

Puedes acortar el código del ejemplo anterior yendo directamente al URI (lo que implica una codificación), como se muestra en el siguiente ejemplo:

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")

Puedes acortarlo aún más usando la plantilla de URI completa, como se muestra en el siguiente ejemplo:

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 y RestTemplate extienden y codifican plantillas de URI internamente utilizando la estrategia UriBuilderFactory. Ambas opciones se pueden configurar usando una estrategia personalizada, como se muestra en el siguiente ejemplo:

Java
String baseUrl = "https://example.com";
DefaultUriBuilderFactory factory = new DefaultUriBuilderFactory(baseUrl)
factory.setEncodingMode(EncodingMode.TEMPLATE_AND_VALUES);
// Configurando RestTemplate...
RestTemplate restTemplate = new RestTemplate();
restTemplate.setUriTemplateHandler(factory);
// Configurando WebClient...
WebClient client = WebClient.builder().uriBuilderFactory(factory).build();
Kotlin
val baseUrl = "https://example.com"
val factory = DefaultUriBuilderFactory(baseUrl).apply {
encodingMode = EncodingMode.TEMPLATE_AND_VALUES
}
Configurando RestTemplate...
val restTemplate = RestTemplate().apply {
uriTemplateHandler = factory
}
// Configurando WebClient...
val client = WebClient.builder().uriBuilderFactory(factory).build()

La implementación DefaultUriBuilderFactory utiliza UriComponentsBuilder internamente para extender y codificar patrones URI. Como fábrica, proporciona un lugar único para configurar el enfoque de codificación, basado en uno de los siguientes modos de codificación:

  • TEMPLATE_AND_VALUES: utiliza UriComponentsBuilder#encode () correspondiente al primera opción en la lista anterior, para precodificar el patrón URI y codificar estrictamente las variables al expandirse.

  • VALUES_ONLY: No codifica el patrón URI y en su lugar, aplica estrictamente la codificación de URI a variables mediante UriUtils#encodeUriVariables antes de expandirlos en una plantilla.

  • URI_COMPONENT: utiliza UriComponents#encode(), correspondiente a la segunda opción de la lista anterior, para codificar el valor de un componente URI después de expandir las variables URI.

  • NONE No se aplica ninguna codificación.

RestTemplate está establecido en EncodingMode.URI_COMPONENT por razones históricas y por compatibilidad con versiones anteriores. WebClient accede al valor predeterminado en DefaultUriBuilderFactory, que se cambió de EncodingMode.URI_COMPONENT en 5.0.x a EncodingMode.TEMPLATE_AND_VALUES en 5.1.