URI在網路請求中必不可少,Spring提供了一些工具類用於解析或者生成URL,比如根據引數生成GET的URL等。本文會對Spring MVC中的URI工具進行介紹,本文主要參考Spring官方文件。
工具類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>
本文最先發布至微信公眾號,版權所有,禁止轉載!