This section describes various options available in the Spring Framework to work with URI’s.
本节描述了 Spring 框架中可用于处理 URI 的各种选项。
Spring MVC and Spring WebFlux
Spring MVC 和 Spring WebFlux
UriComponentsBuilder helps to build URI’s from URI templates with variables, as the following example shows:
UriComponentsBuilder 帮助从带有变量的 URI 模板中构建 URI,如下例所示:
1
Static factory method with a URI template.
静态工厂方法与 URI 模板。
2
Add or replace URI components.
添加或替换 URI 组件。
3
Request to have the URI template and URI variables encoded.
请求对 URI 模板和 URI 变量进行编码。
4
Build a UriComponents. 构建一个 UriComponents 。
5
Expand variables and obtain the URI.
展开变量并获取 URI 。
1
Static factory method with a URI template.
2
Add 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.
The preceding example can be consolidated into one chain and shortened with buildAndExpand, as the following example
shows:
前一个示例可以合并为一个链,并用 buildAndExpand 缩短,如下例所示:
You can shorten it further by going directly to a URI (which implies encoding), as the following example shows:
您可以通过直接访问 URI(这表示编码)来进一步缩短它,如下例所示:
You can shorten it further still with a full URI template, as the following example shows:
您可以使用完整的 URI 模板进一步缩短,如下例所示:
Spring MVC and Spring WebFlux
Spring MVC 和 Spring WebFlux
UriComponentsBuilder implements UriBuilder. You can create a UriBuilder, in turn, 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 other details.
UriComponentsBuilder 实现 UriBuilder 。您可以使用 UriBuilderFactory 创建一个 UriBuilder ,从而 UriBuilderFactory
和 UriBuilder 提供了一种基于共享配置(如基础 URL、编码偏好和其他详细信息)的可插拔机制,用于从 URI 模板构建 URI。
You can configure RestTemplate and WebClient 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.
您可以使用 RestTemplate 和 WebClient 配置 UriBuilderFactory 以自定义 URI 的准备。 DefaultUriBuilderFactory 是
UriBuilderFactory 的默认实现,它内部使用 UriComponentsBuilder 并公开共享配置选项。
The following example shows how to configure a RestTemplate:
以下示例展示了如何配置一个 RestTemplate :
The following example configures a WebClient:
以下示例配置了一个 WebClient :
In addition, you can also use DefaultUriBuilderFactory directly. It is similar to using UriComponentsBuilder but,
instead of static factory methods, it is an actual instance that holds configuration and preferences, as the following
example shows:
此外,您还可以直接使用 DefaultUriBuilderFactory 。它与使用 UriComponentsBuilder
类似,但不同之处在于,它不是一个静态工厂方法,而是一个实际实例,它包含配置和首选项,如下例所示:
Spring MVC and Spring WebFlux
Spring MVC 和 Spring WebFlux
UriComponentsBuilder exposes encoding options at two levels:
UriComponentsBuilder 在两个级别上公开编码选项:
UriComponentsBuilder#encode():
Pre-encodes the URI template first and then strictly encodes URI variables when expanded.
UriComponentsBuilder#encode():首先预编码 URI 模板,然后在展开时严格编码 URI 变量。
UriComponents#encode():
Encodes URI components after URI variables are expanded.
UriComponents#encode():在展开 URI 变量后对 URI 组件进行编码。
Both options replace non-ASCII and illegal characters with escaped octets. However, the first option also replaces
characters with reserved meaning that appear in URI variables.
两个选项都将非 ASCII 码和非法字符替换为转义八进制数。然而,第一个选项还将出现在 URI 变量中的具有保留意义的字符替换掉。
Consider ";", which is legal in a path but has reserved meaning. The first option replaces ";" with "%3B" in URI
variables but not in the URI template. By contrast, the second option never replaces ";", since it is a legal character
in a path.
考虑分号";",它在路径中是合法的,但具有保留意义。第一种选项在 URI 变量中将分号替换为"%3B",但不在 URI
模板中替换。相比之下,第二种选项从不替换分号,因为它在路径中是一个合法字符。
For most cases, the first option is likely to give the expected result, because it treats URI variables as opaque data
to be fully encoded, while the second option is useful if URI variables do intentionally contain reserved characters.
对于大多数情况,第一个选项更有可能给出预期的结果,因为它将 URI 变量视为不可见的数据进行完全编码,而第二个选项在 URI
变量故意包含保留字符时很有用。
The second option is also useful when not expanding URI variables at all since that will also encode anything that
incidentally looks like a URI variable.
第二种选项在完全不扩展 URI 变量时也有用,因为那样也会对任何偶然看起来像 URI 变量的内容进行编码。
The following example uses the first option:
以下示例使用第一个选项:
You can shorten the preceding example by going directly to the URI (which implies encoding), as the following example
shows:
您可以直接通过 URI(这意味着编码)来缩短前面的示例,如下例所示:
You can shorten it further still with a full URI template, as the following example shows:
您可以使用完整的 URI 模板进一步缩短,如下例所示:
The WebClient and the RestTemplate expand and encode URI templates internally through the UriBuilderFactory
strategy. Both can be configured with a custom strategy, as the following example shows:
WebClient 和 RestTemplate 通过 UriBuilderFactory 策略内部扩展和编码 URI 模板。两者都可以配置为自定义策略,如下例所示:
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:
该 DefaultUriBuilderFactory 实现内部使用 UriComponentsBuilder 来扩展和编码 URI
模板。作为一个工厂,它提供了一个配置编码方法的单一位置,基于以下编码模式之一:
TEMPLATE_AND_VALUES: Uses UriComponentsBuilder#encode(), corresponding to the first option in the earlier list, to
pre-encode the URI template and strictly encode URI variables when expanded.
TEMPLATE_AND_VALUES :使用 UriComponentsBuilder#encode() ,对应于之前列表中的第一个选项,以预编码 URI 模板并在展开时严格编码
URI 变量。
VALUES_ONLY: Does not encode the URI template and, instead, applies strict encoding to URI variables through
UriUtils#encodeUriVariables prior to expanding them into the template.
VALUES_ONLY : 不对 URI 模板进行编码,而是在将其扩展到模板之前,通过 UriUtils#encodeUriVariables 对 URI 变量进行严格的编码。
URI_COMPONENT: Uses UriComponents#encode(), corresponding to the second option in the earlier list, to encode URI
component value after URI variables are expanded.
URI_COMPONENT : 使用 UriComponents#encode() ,对应于之前列表中的第二个选项,在展开 URI 变量后对 URI 组件值进行编码。
NONE: No encoding is applied.
NONE : 没有应用编码。
The RestTemplate is set to EncodingMode.URI_COMPONENT for historic reasons and for backwards compatibility. The
WebClient relies on the default value in DefaultUriBuilderFactory, which was changed from
EncodingMode.URI_COMPONENT in 5.0.x to EncodingMode.TEMPLATE_AND_VALUES in 5.1.
RestTemplate 设置为 EncodingMode.URI_COMPONENT 是出于历史原因和向后兼容性的考虑。 WebClient 依赖于
DefaultUriBuilderFactory 中的默认值,该值在 5.0.x 中从 EncodingMode.URI_COMPONENT 更改为 5.1 中的
EncodingMode.TEMPLATE_AND_VALUES 。
1.5.4. 相对 Servlet 请求
You can use ServletUriComponentsBuilder to create URIs relative to the current request, as the following example
shows:
您可以使用 ServletUriComponentsBuilder 创建相对于当前请求的 URI,如下例所示:
You can create URIs relative to the context path, as the following example shows:
您可以根据上下文路径创建相对 URI,如下例所示:
You can create URIs relative to a Servlet (for example, /main/*), as the following example shows:
您可以创建相对于 Servlet 的 URI(例如, /main/* ),如下例所示:
As of 5.1, ServletUriComponentsBuilder ignores information from the Forwarded and X-Forwarded-* headers, which
specify the client-originated address. Consider using the ForwardedHeaderFilter to
extract and use or to discard such headers.
截至 5.1 版本, ServletUriComponentsBuilder 忽略了来自 Forwarded 和 X-Forwarded-* 头部的信息,这些头部指定了客户端源地址。请考虑使用
ForwardedHeaderFilter 来提取和使用或丢弃此类头部。
1.5.5. 控制器链接
Spring MVC provides a mechanism to prepare links to controller methods. For example, the following MVC controller allows
for link creation:
Spring MVC 提供了一种准备控制器方法链接的机制。例如,以下 MVC 控制器允许创建链接:
You can prepare a link by referring to the method by name, as the following example shows:
您可以通过按名称引用方法来准备一个链接,如下例所示:
In the preceding example, we provide actual method argument values (in this case, the long value: 21) to be used as a
path variable and inserted into the URL. Furthermore, we provide the value, 42, to fill in any remaining URI
variables, such as the hotel variable inherited from the type-level request mapping. If the method had more arguments,
we could supply null for arguments not needed for the URL. In general, only @PathVariable and @RequestParam
arguments are relevant for constructing the URL.
在前面示例中,我们提供了实际方法参数值(在这种情况下,长整型值: 21 ),用作路径变量并插入到 URL 中。此外,我们还提供了值,
42 ,以填充任何剩余的 URI 变量,例如从类型级别请求映射继承的 hotel 变量。如果方法有更多参数,我们可以为不需要用于 URL
的参数提供 null。一般来说,只有 @PathVariable 和 @RequestParam 参数与构造 URL 相关。
There are additional ways to use MvcUriComponentsBuilder. For example, you can use a technique akin to mock testing
through proxies to avoid referring to the controller method by name, as the following example shows (the example assumes
static import of MvcUriComponentsBuilder.on):
存在其他使用 MvcUriComponentsBuilder 的方法。例如,您可以通过类似于通过代理进行模拟测试的技术来避免通过名称引用控制器方法,如下例所示(该示例假设静态导入
MvcUriComponentsBuilder.on ):
Controller method signatures are limited in their design when they are supposed to be usable for link creation with
fromMethodCall. Aside from needing a proper parameter signature, there is a technical limitation on the return type (
namely, generating a runtime proxy for link builder invocations), so the return type must not be final. In particular,
the common String return type for view names does not work here. You should use ModelAndView or even plain
Object (with a String return value) instead.
控制器方法签名在设计上有限,当它们应该与 fromMethodCall
一起用于创建链接时。除了需要一个合适的参数签名外,还存在对返回类型的限制(即生成用于链接构建器调用的运行时代理),因此返回类型不能是
final 。特别是,对于视图名称的常见 String 返回类型在这里不适用。你应该使用 ModelAndView 或者甚至纯 Object (带有
String 返回值)代替。
The earlier examples use static methods in MvcUriComponentsBuilder. Internally, they rely on
ServletUriComponentsBuilder to prepare a base URL from the scheme, host, port, context path, and servlet path of the
current request. This works well in most cases. However, sometimes, it can be insufficient.
早期示例使用 MvcUriComponentsBuilder 中的静态方法。内部,它们依赖于 ServletUriComponentsBuilder 从当前请求的方案、主机、端口、上下文路径和
servlet 路径准备基本 URL。这在大多数情况下都很好用。然而,有时这可能不够。
For example, you may be outside the context of a request (such as a batch process that prepares links) or perhaps you
need to insert a path prefix (such as a locale prefix that was removed from the request path and needs to be re-inserted
into links).
例如,您可能处于请求上下文之外(例如,准备链接的批处理过程)或者可能需要插入路径前缀(例如,从请求路径中移除的本地化前缀,需要重新插入到链接中)。
For such cases, you can use the static fromXxx overloaded methods that accept a UriComponentsBuilder to use a base
URL. Alternatively, you can create an instance of MvcUriComponentsBuilder with a base URL and then use the
instance-based withXxx methods. For example, the following listing uses withMethodCall:
对于此类情况,您可以使用接受一个 UriComponentsBuilder 的静态 fromXxx 重载方法来使用基本 URL。或者,您可以使用带有基本
URL 的 MvcUriComponentsBuilder 实例,然后使用基于实例的 withXxx 方法。例如,以下列表使用 withMethodCall :
As of 5.1, MvcUriComponentsBuilder ignores information from the Forwarded and X-Forwarded-* headers, which specify
the client-originated address. Consider using the ForwardedHeaderFilter to extract and use
or to discard such headers.
截至 5.1 版本, MvcUriComponentsBuilder 忽略了来自 Forwarded 和 X-Forwarded-* 头部的信息,这些头部指定了客户端原始地址。请考虑使用
ForwardedHeaderFilter 来提取和使用或丢弃此类头部。
1.5.6. 视图中的链接
In views such as Thymeleaf, FreeMarker, or JSP, you can build links to annotated controllers by referring to the
implicitly or explicitly assigned name for each request mapping.
在 Thymeleaf、FreeMarker 或 JSP 等视图中,您可以通过引用每个请求映射的隐式或显式分配的名称来构建指向注解控制器的链接。
Consider the following example:
考虑以下示例:
Given the preceding controller, you can prepare a link from a JSP, as follows:
给定前面的控制器,您可以从 JSP 中准备一个链接,如下所示:
The preceding example relies on the mvcUrl function declared in the Spring tag library (that is, META-INF/spring.tld),
but it is easy to define your own function or prepare a similar one for other templating technologies.
前一个示例依赖于在 Spring 标签库中声明的 mvcUrl 函数(即 META-INF/spring.tld),但定义自己的函数或为其他模板技术准备一个类似的函数很容易。
Here is how this works. On startup, every @RequestMapping is assigned a default name through
HandlerMethodMappingNamingStrategy, whose default implementation uses the capital letters of the class and the method
name (for example, the getThing method in ThingController becomes "TC#getThing"). If there is a name clash, you can
use @RequestMapping(name="..") to assign an explicit name or implement your own
HandlerMethodMappingNamingStrategy.
这里是如何工作的。在启动时,每个 @RequestMapping 都会通过 HandlerMethodMappingNamingStrategy
分配一个默认名称,其默认实现使用类的首字母和方法名称(例如, ThingController 中的 getThing 方法变为"TC#getThing"
)。如果有名称冲突,您可以使用 @RequestMapping(name="..") 分配一个显式名称或实现自己的
HandlerMethodMappingNamingStrategy 。