http://docs.spring.io/spring/docs/current/spring-framework-reference/html/mvc.html#mvc-uri-building
Spring MVC 提供了一種機制,可以構造和編碼URI -- 使用UriComponentsBuilder和UriComponents。
例:
UriComponents uriComponents = UriComponentsBuilder.fromUriString( "http://example.com/hotels/{hotel}/bookings/{booking}").build(); URI uri = uriComponents.expand("42", "21").encode().toUri();
嗯,expand()是用於替換所有的模板變量,encode默認使用UTF8編碼。
注意,UriComponents是不可變的,expand()和encode()都是返回新的實例。
你還可以這樣做:
UriComponents uriComponents = UriComponentsBuilder.newInstance() .scheme("http").host("example.com").path("/hotels/{hotel}/bookings/{booking}").build() .expand("42", "21") .encode();
在Servlet環境中,使用子類ServletUriComponentsBuilder提供的靜態工廠方法可以從一個Servlet request中獲取有用的URI信息:
HttpServletRequest request = ... // Re-use host, scheme, port, path and query string // Replace the "accountId" query param ServletUriComponentsBuilder ucb = ServletUriComponentsBuilder.fromRequest(request) .replaceQueryParam("accountId", "{id}").build() .expand("123") .encode();
或者,你還可以選擇復制這些可用信息的一個子集:
// Re-use host, port and context path // Append "/accounts" to the path ServletUriComponentsBuilder ucb = ServletUriComponentsBuilder.fromContextPath(request) .path("/accounts").build()
或者,當DispatcherServlet按名字被映射時(如 /main/*),你也可以擁有servlet映射的字面部分(???什么鬼):
// Re-use host, port, context path // Append the literal part of the servlet mapping to the path // Append "/accounts" to the path ServletUriComponentsBuilder ucb = ServletUriComponentsBuilder.fromServletMapping(request) .path("/accounts").build()
1、構造連接到controllers和methods的URIs
Spring MVC也提供了一種機制,以構造到controller methods的連接。例如,當給定以下controller時:
@Controller @RequestMapping("/hotels/{hotel}") public class BookingController { @GetMapping("/bookings/{booking}") public String getBooking(@PathVariable Long booking) { // ... } }
你可以通過名字引用該方法,來准備一個連接:
UriComponents uriComponents = MvcUriComponentsBuilder .fromMethodName(BookingController.class, "getBooking", 21).buildAndExpand(42); URI uri = uriComponents.encode().toUri();
中上面的例子中,我們提供了實際的方法參數值,21。更進一步,我們還提供了42以填補剩余的URI變量,例如”hotel”。如果該方法擁有更多參數,你可以為那些不需要出現在URI中的參數提供null。一般來說,只有@PathVariable和@RequestParam參數與構建URL相關。
還有其他方式來使用MvcUriComponentsBuilder。例如,你可以使用一種技術族來模擬測試 -- 通過代理以避免通過名字引用controller name (下例假定已靜態導入了MvcUriComponentsBuilder.on):
UriComponents uriComponents = MvcUriComponentsBuilder .fromMethodCall(on(BookingController.class).getBooking(21)).buildAndExpand(42); URI uri = uriComponents.encode().toUri();
上例中,使用了MvcUriComponentsBuilder中的靜態方法。在內部,他們依賴於ServletUriComponentsBuilder 來准備一個base URL -- 基於當前request的scheme、host、port、context path以及 servlet path。大多數時候這樣很有效,然而,有時候也是不夠的。例如,你可能在request的context之外(例如,准備links的批處理),或者你需要插入一個path前綴 (例如,locale前綴 -- 從request path中被移除過的,且需要被重新插入連接)。
這些情況下,你可以使用靜態的”fromXxx”方法的重載 -- 那些接收一個UriComponentsBuilder的方法,來使用base URL。或者,你可以使用一個base URL來創建MvcUriComponentsBuilder的實例,然后使用該實例的”withXxx”方法。 例如:
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();
2、從views構建連接到controllers和methods的URIs
你還可以從views(如JSP、Thymeleaf、FreeMarker)構建到注解controllers的連接。使用MvcUriComponentsBuilder的fromMappingName(..)方法即可。
每個@RequestMapping都被給定了一個默認的名字 -- 基於class的大寫字母和全方法名。例如,FooController中的getFoo方法,被賦予了名字”FC#getFoo”。這種策略可以被替換或定制--通過創建一個HandlerMethodMappingNamingStrategy實例,再將其插入你的RequestMappingHandlerMapping即可。默認的策略實現還要看一下@RequestMapping的name attribute,如果有則使用。這意味着,如果默認被賦予的映射名字與其他的發生了沖突(例如,重載的方法),你可以給該@RequestMapping顯式的賦予一個name。
被賦予的請求映射名字,在啟動時會被以TRACE級別記錄。
Spring JSP tag庫 提供了一個功能,叫做mvcUrl,可被用於基於該機制准備到controller methods的連接。
例如,當給定以下controller時:
@RequestMapping("/people/{id}/addresses")
public class PersonAddressController {
@RequestMapping("/{country}")
public HttpEntity getAddress(@PathVariable String country) { ... }
}
你可以准備一個連接--從JSP中,如下:
<%@ taglib uri="http://www.springframework.org/tags" prefix="s" %>
...
<a href="${s:mvcUrl('PAC#getAddress').arg(0,'US').buildAndExpand('123')}">Get Address</a>
上面的例子依賴於Spring 標簽庫(如 META-INF/spring.tld)中聲明的mvcUrl JSP功能。
-- 好吧, 看完了,明白功能,但是,干嘛用的???測試嗎?還是類似HttpClient或者RestTemplate的功能?
