URI 在网络申请中必不可少,Spring 提供了一些工具类用于解析或者生成 URL,比方依据参数生成 GET 的 URL 等。本文会对 Spring MVC 中的 URI 工具进行介绍,本文次要参考 Spring 官网文档。
<!–more–>
工具类 UriComponents
UriComponentsBuilder 能够用于依据 URL 和参数来构建门路,比方咱们须要一个带 GET 参数的 URL,通常状况下咱们须要本人去拼接 URL,增加 ”&” 和 ”? 等参数 ”。UriComponentsBuilder 提供一种更简介的办法去构建 URL:
UriComponents uriComponents = UriComponentsBuilder
.fromUriString("https://example.com/hotels/{hotel}")
.queryParam("q", "{q}")
.encode()
.build();
// https://example.com/hotels/Westin?q=123
URI uri = uriComponents.expand("Westin", "123").toUri();
下面的两条语句也能够合并到一个 Build 链中,用如下形式达到同样的目标:
URI uri = UriComponentsBuilder
.fromUriString("https://example.com/hotels/{hotel}")
.queryParam("q", "{q}")
.encode()
.buildAndExpand("Westin", "123")
.toUri();
URI uri = UriComponentsBuilder
.fromUriString("https://example.com/hotels/{hotel}")
.queryParam("q", "{q}")
.build("Westin", "123");
URI uri = UriComponentsBuilder
.fromUriString("https://example.com/hotels/{hotel}?q={q}")
.build("Westin", "123");
接口 UriBuilder
UriComponentsBuilder 实现了 UriBuilder 接口,该接口的次要性能就是构建 Uri。Spring 中能够通过 UriBuilderFactory 获取 UriBuilder 的实例。咱们平时应用 httpClient 类如 Spring 的 RestTemplate,并不需要本人拼接 Uri,只须要输出参数组件会主动拼接 Url。对于过 Spring 的 RestTemplate,其外部应用的 Url 组件就是 UriBuilderFactory。
// 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;
String baseUrl = "https://example.org";
DefaultUriBuilderFactory factory = new DefaultUriBuilderFactory(baseUrl);
factory.setEncodingMode(EncodingMode.TEMPLATE_AND_VALUES);
WebClient client = WebClient.builder().uriBuilderFactory(factory).build();
String baseUrl = "https://example.com";
DefaultUriBuilderFactory uriBuilderFactory = new DefaultUriBuilderFactory(baseUrl);
URI uri = uriBuilderFactory.uriString("/hotels/{hotel}")
.queryParam("q", "{q}")
.build("Westin", "123");
Url 的编码
UriComponentsBuilder 组件提供了两种类型的编码方式:
- UriComponentsBuilder#encode():对 Url 模板和参数别离进行编码之后进行拼接。
- UriComponents#encode():对拼接后的 Url 进行编码操作。
大多数状况下适宜应用 UriComponentsBuilder#encode(),因为它将参数独自进行了编码。然而如果你须要在编码中保留特殊字符,那么最好应用第二种编码方式。
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"
Servlet Uri 构建
Spring 提供了另一个 Uri 组件 ServletUriComponentsBuilder,该组件能够基于 Servlet 申请构建新的 Uri:
HttpServletRequest request = ...
// Re-uses host, scheme, port, path and query string...
ServletUriComponentsBuilder ucb = ServletUriComponentsBuilder.fromRequest(request)
.replaceQueryParam("accountId", "{id}").build()
.expand("123")
.encode();
// Re-uses host, port and context path...
ServletUriComponentsBuilder ucb = ServletUriComponentsBuilder.fromContextPath(request).path("/accounts").build()
// Re-uses host, port, context path, and Servlet prefix...
ServletUriComponentsBuilder ucb = ServletUriComponentsBuilder.fromServletMapping(request).path("/accounts").build()
Controller Uri
咱们晓得 Spring 中能够通过 @RequestMapping 把一个申请映射到 Controller 的办法上,那么咱们如何获取到 Controller 办法的申请门路呢?
@Controller
@RequestMapping("/hotels/{hotel}")
public class BookingController {@GetMapping("/bookings/{booking}")
public ModelAndView getBooking(@PathVariable Long booking) {// ...}
}
Spring 提供了 MvcUriComponentsBuilder 工具获取 Controller 办法对应的门路,其应用示例如下所示:
// 21: 指明参数的类型, 42: 新的参数类型.
UriComponents uriComponents = MvcUriComponentsBuilder
.fromMethodName(BookingController.class, "getBooking", 21).buildAndExpand(42);
URI uri = uriComponents.encode().toUri();
UriComponents uriComponents = MvcUriComponentsBuilder
.fromMethodCall(on(BookingController.class).getBooking(21)).buildAndExpand(42);
URI uri = uriComponents.encode().toUri();
Controller 办法应该是非 Final 的,否则 Spring 可能会获取不到配置的门路信息。
MvcUriComponentsBuilder 还反对指定 Context,如域名等信息,示例如下所示:
UriComponentsBuilder base = ServletUriComponentsBuilder.fromCurrentContextPath().path("/en");
MvcUriComponentsBuilder builder = MvcUriComponentsBuilder.relativeTo(base);
builder.withMethodCall(on(BookingController.class).getBooking(21)).buildAndExpand(42);
URI uri = uriComponents.encode().toUri();
视图中的 URL
在 Thymeleaf、FreeMarker 和 JSP 等视图组件中,咱们能够通过视图 URL 组件去拼接 URL,示例如下:
@RequestMapping("/people/{id}/addresses")
public class PersonAddressController {@RequestMapping("/{country}")
public HttpEntity<PersonAddress> getAddress(@PathVariable String country) {...}
}
<%@ taglib uri="http://www.springframework.org/tags" prefix="s" %>
...
<a href="${s:mvcUrl('PAC#getAddress').arg(0,'US').buildAndExpand('123')}">Get Address</a>
本文最先公布至微信公众号,版权所有,禁止转载!