此版本仍在开发中,尚不被认为是稳定的。对于最新的稳定版本,请使用 Spring Framework 6.2.10! |
URI 链接
本节介绍 Spring Framework 中可用于准备 URI 的各种选项。
Uri组件
Spring MVC 和 Spring WebFlux
UriComponentsBuilder
有助于从带有变量的 URI 模板构建 URI,如以下示例所示:
-
Java
-
Kotlin
UriComponents uriComponents = UriComponentsBuilder
.fromUriString("https://example.com/hotels/{hotel}") (1)
.queryParam("q", "{q}") (2)
.encode() (3)
.build(); (4)
URI uri = uriComponents.expand("Westin", "123").toUri(); (5)
1 | 带有 URI 模板的静态工厂方法。 |
2 | 添加或替换 URI 组件。 |
3 | 请求对 URI 模板和 URI 变量进行编码。 |
4 | 构建一个UriComponents . |
5 | 展开变量并获取URI . |
val uriComponents = UriComponentsBuilder
.fromUriString("https://example.com/hotels/{hotel}") (1)
.queryParam("q", "{q}") (2)
.encode() (3)
.build() (4)
val uri = uriComponents.expand("Westin", "123").toUri() (5)
1 | 带有 URI 模板的静态工厂方法。 |
2 | 添加或替换 URI 组件。 |
3 | 请求对 URI 模板和 URI 变量进行编码。 |
4 | 构建一个UriComponents . |
5 | 展开变量并获取URI . |
前面的示例可以合并为一个链,并使用buildAndExpand
,
如以下示例所示:
-
Java
-
Kotlin
URI uri = UriComponentsBuilder
.fromUriString("https://example.com/hotels/{hotel}")
.queryParam("q", "{q}")
.encode()
.buildAndExpand("Westin", "123")
.toUri();
val uri = UriComponentsBuilder
.fromUriString("https://example.com/hotels/{hotel}")
.queryParam("q", "{q}")
.encode()
.buildAndExpand("Westin", "123")
.toUri()
您可以通过直接转到 URI(这意味着编码)来进一步缩短它, 如以下示例所示:
-
Java
-
Kotlin
URI uri = UriComponentsBuilder
.fromUriString("https://example.com/hotels/{hotel}")
.queryParam("q", "{q}")
.build("Westin", "123");
val uri = UriComponentsBuilder
.fromUriString("https://example.com/hotels/{hotel}")
.queryParam("q", "{q}")
.build("Westin", "123")
您可以使用完整的 URI 模板进一步缩短它,如以下示例所示:
-
Java
-
Kotlin
URI uri = UriComponentsBuilder
.fromUriString("https://example.com/hotels/{hotel}?q={q}")
.build("Westin", "123");
val uri = UriComponentsBuilder
.fromUriString("https://example.com/hotels/{hotel}?q={q}")
.build("Westin", "123")
UriBuilder
Spring MVC 和 Spring WebFlux
UriComponentsBuilder
实现UriBuilder
.您可以创建一个UriBuilder
,反过来,使用UriBuilderFactory
.一起UriBuilderFactory
和UriBuilder
提供一种可插拔的机制,用于从 URI 模板构建 URI,基于
共享配置,例如基本 URL、编码首选项和其他详细信息。
您可以配置RestTemplate
和WebClient
使用UriBuilderFactory
自定义 URI 的准备。DefaultUriBuilderFactory
是默认的
实现UriBuilderFactory
使用UriComponentsBuilder
内部和
公开共享配置选项。
以下示例演示如何配置RestTemplate
:
-
Java
-
Kotlin
// 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);
// 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
以下示例配置WebClient
:
-
Java
-
Kotlin
// 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();
// 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()
此外,您还可以使用DefaultUriBuilderFactory
径直。这类似于使用UriComponentsBuilder
但是,它不是静态工厂方法,而是一个实际实例
,其中包含配置和首选项,如以下示例所示:
-
Java
-
Kotlin
String baseUrl = "https://example.com";
DefaultUriBuilderFactory uriBuilderFactory = new DefaultUriBuilderFactory(baseUrl);
URI uri = uriBuilderFactory.uriString("/hotels/{hotel}")
.queryParam("q", "{q}")
.build("Westin", "123");
val baseUrl = "https://example.com"
val uriBuilderFactory = DefaultUriBuilderFactory(baseUrl)
val uri = uriBuilderFactory.uriString("/hotels/{hotel}")
.queryParam("q", "{q}")
.build("Westin", "123")
URI 解析
Spring MVC 和 Spring WebFlux
UriComponentsBuilder
支持两种 URI 解析器类型:
-
RFC 解析器 — 此解析器类型期望 URI 字符串符合 RFC 3986 语法, 并将偏离语法视为非法。
-
WhatWG 解析器 — 此解析器基于 WhatWG URL Living 标准中的 URL 解析算法。它提供了宽松的处理 各种意外输入的情况。浏览器实现此作是为了处理 宽容用户键入的 URL。有关更多详细信息,请参阅 URL Living Standard 和 URL 解析测试用例。
默认情况下,RestClient
,WebClient
和RestTemplate
使用 RFC 解析器类型,并且期望应用程序提供符合 RFC 语法的 URL 模板。要更改您可以自定义UriBuilderFactory
在任何客户端上。
应用程序和框架可能进一步依赖UriComponentsBuilder
满足他们自己的需要解析用户提供的 URL,以便检查和可能验证的 URI 组件例如方案、主机、端口、路径和查询。此类组件可以决定使用WhatWG 解析器类型,以便更宽松地处理 URL,并与浏览器解析 URI,以防重定向到输入 URL 或包含在对浏览器的响应中。
URI 编码
Spring MVC 和 Spring WebFlux
UriComponentsBuilder
在两个级别公开编码选项:
-
UriComponentsBuilder#encode():首先对 URI 模板进行预编码,然后在展开时严格编码 URI 变量。
-
UriComponents#encode(): 在 URI 变量展开后对 URI 组件进行编码。
这两个选项都将非 ASCII 和非法字符替换为转义八位字节。但是,第一个选项 还会替换 URI 变量中出现的具有保留含义的字符。
考虑“;”,它在路径中是合法的,但具有保留的含义。第一个选项将 “;”在 URI 变量中与“%3B”一起使用,但在 URI 模板中没有。相比之下,第二种选择从来不会 替换 “;”,因为它是路径中的法定字符。 |
在大多数情况下,第一个选项可能会给出预期的结果,因为它处理 URI 变量作为要完全编码的不透明数据,而第二个选项在 URI 变量确实有意包含保留字符。第二个选项也很有用 当根本不扩展 URI 变量时,因为这也会对任何 顺便说一句,看起来像一个 URI 变量。
以下示例使用第一个选项:
-
Java
-
Kotlin
URI uri = UriComponentsBuilder.fromPath("/hotel list/{city}")
.queryParam("q", "{q}")
.encode()
.buildAndExpand("New York", "foo+bar")
.toUri();
// Result is "/hotel%20list/New%20York?q=foo%2Bbar"
val uri = UriComponentsBuilder.fromPath("/hotel list/{city}")
.queryParam("q", "{q}")
.encode()
.buildAndExpand("New York", "foo+bar")
.toUri()
// Result is "/hotel%20list/New%20York?q=foo%2Bbar"
您可以通过直接转到 URI(这意味着编码) 来缩短前面的示例, 如以下示例所示:
-
Java
-
Kotlin
URI uri = UriComponentsBuilder.fromPath("/hotel list/{city}")
.queryParam("q", "{q}")
.build("New York", "foo+bar");
val uri = UriComponentsBuilder.fromPath("/hotel list/{city}")
.queryParam("q", "{q}")
.build("New York", "foo+bar")
您可以使用完整的 URI 模板进一步缩短它,如以下示例所示:
-
Java
-
Kotlin
URI uri = UriComponentsBuilder.fromUriString("/hotel list/{city}?q={q}")
.build("New York", "foo+bar");
val uri = UriComponentsBuilder.fromUriString("/hotel list/{city}?q={q}")
.build("New York", "foo+bar")
这WebClient
和RestTemplate
通过内部扩展和编码 URI 模板 这UriBuilderFactory
策略。 两者都可以配置自定义策略,如以下示例所示:
-
Java
-
Kotlin
String baseUrl = "https://example.com";
DefaultUriBuilderFactory factory = new DefaultUriBuilderFactory(baseUrl)
factory.setEncodingMode(EncodingMode.TEMPLATE_AND_VALUES);
// Customize the RestTemplate..
RestTemplate restTemplate = new RestTemplate();
restTemplate.setUriTemplateHandler(factory);
// Customize the WebClient..
WebClient client = WebClient.builder().uriBuilderFactory(factory).build();
val baseUrl = "https://example.com"
val factory = DefaultUriBuilderFactory(baseUrl).apply {
encodingMode = EncodingMode.TEMPLATE_AND_VALUES
}
// Customize the RestTemplate..
val restTemplate = RestTemplate().apply {
uriTemplateHandler = factory
}
// Customize the WebClient..
val client = WebClient.builder().uriBuilderFactory(factory).build()
这DefaultUriBuilderFactory
实现用途UriComponentsBuilder
内部展开和编码 URI 模板。作为工厂,它提供了一个配置编码方法,基于以下编码模式之一:
-
TEMPLATE_AND_VALUES
:使用UriComponentsBuilder#encode()
,对应于 前面列表中的第一个选项,用于预编码 URI 模板并在 扩大。 -
VALUES_ONLY
:不对 URI 模板进行编码,而是应用严格的编码 到 URI 变量UriUtils#encodeUriVariables
在将它们扩展到 模板。 -
URI_COMPONENT
:使用UriComponents#encode()
,对应于前面列表中的第二个选项,设置为 在 URI 变量展开后对 URI 组件值进行编码。 -
NONE
:不应用编码。
这RestTemplate
设置为EncodingMode.URI_COMPONENT
对于历史
原因和向后兼容性。这WebClient
依赖于默认值
在DefaultUriBuilderFactory
,从EncodingMode.URI_COMPONENT
在
5.0.x 到EncodingMode.TEMPLATE_AND_VALUES
在 5.1 中。