SpringMVC 教程 - URI 鏈接


原文鏈接:https://www.codemore.top/cates/Backend/post/2018-04-22/spring-mvc-uri-links

這一節主要講的是Spring Framework組成URI的各種選項。

UriComponents

UriComponentsjava.net.URI類似。但是UriComponents有一個專用的UriComponentsBuilder來構建,並且支持模版變量。例如

String uriTemplate = "http://example.com/hotels/{hotel}"; UriComponents uriComponents = UriComponentsBuilder.fromUriString(uriTemplate) 1 .queryParam("q", "{q}") 2 .build(); 3 URI uri = uriComponents.expand("Westin", "123").encode().toUri(); 4

解釋:

  1. 包含URI模版的靜態工廠方法
  2. 添加或者替代URI組件
  3. 構建UriComponents
  4. 擴展URI變量,編碼獲取URI變量

上述步驟合起來可以如下表示:

String uriTemplate = "http://example.com/hotels/{hotel}"; URI uri = UriComponentsBuilder.fromUriString(uriTemplate) .queryParam("q", "{q}") .buildAndExpand("Westin", "123") .encode() .toUri();
UriBuilder

UriComponentsBuilderUriBuilder的子類。UriBuilderFactoryUriBuilder合在一起提供了通過URI模版獲取URI的一套可插拔的機制,同樣也提供了一種共享公共屬性,基礎URI,編碼策略等的方式。 RestTemplateWebClient都可以通過UriBuilderFactory配置。默認實現依賴於內部的UriComponentsBuilder,同時提供選項配置基礎URI,編碼策略等。 RestTemplate方式:

String baseUrl = "http://example.com"; DefaultUriBuilderFactory factory = new DefaultUriBuilderFactory(baseUrl); RestTemplate restTemplate = new RestTemplate(); restTemplate.setUriTemplateHandler(factory);

WebClient方式:

String baseUrl = "http://exaplme.com"; DefaultUriBuilderFactory factory = new DefaultUriBuilderFactory(baseUrl); // Configure the UriBuilderFactory.. WebClient client = WebClient.builder().uriBuilderFactory(factory).build(); // Or use shortcut on builder.. WebClient client = WebClient.builder().baseUrl(baseUrl).build(); // Or use create shortcut... WebClient client = WebClient.create(baseUrl);

同樣像直接使用UriComponentsBuilder一樣,也可以直接使用DefaultUriBuilderFactory。唯一的區別是DefaultUriBuilderFactory是無狀態的,並且可以重用。例如:

String baseUrl = "http://example.com"; DefaultUriBuilderFactory uriBuilderFactory = new DefaultUriBuilderFactory(baseUrl); URI uri = uriBuilderFactory.uriString("/hotels/{hotel}") .queryParam("q", "{q}") .build("Westin", "123"); // encoding strategy applied..
URI 編碼

UriComponets中編碼URI的步驟如下:

  1. 擴展URI變量
  2. 每個URI組件(path,query等)都單獨編碼

編碼規則如下:對所有非法字符應用百分號編碼方式,包括非ASCII的字符和在RFC 3986中定義的非法字符。 上述編碼規則並沒有對有保留意義的字符編碼,只是對URI組件中的非法字符盡心編碼,如果想要對其編碼,可以修改編碼策略使其全部編碼。 當使用 DefaultUriBuilderFactory(在WebClient,RestTemplate中使用或者直接使用)時可以如下選擇編碼方式:

String baseUrl = "http://example.com"; DefaultUriBuilderFactory factory = new DefaultUriBuilderFactory(baseUrl) factory.setEncodingMode(EncodingMode.VALUES_ONLY);
Servlet 請求

可以使用ServletUriComponentsBuilder來創建相對於當前請求的URI,例如:

HttpServletRequest request = ...

// Re-uses host, scheme, port, path and query string... ServletUriComponentsBuilder ucb = ServletUriComponentsBuilder.fromRequest(request) .replaceQueryParam("accountId", "{id}").build() .expand("123") .encode();

創建相對於當前context的URI

// Re-uses host, port and context path... ServletUriComponentsBuilder ucb = ServletUriCompontentsBuilder.fromContextPath(request) .path("/accounts").build();

創建相對於Servlet(例如:/main/*)的URI

// Re-uses host, port, context path, and Servlet prefix... ServletUriComponentsBuilder ucb = ServletUriComponentsBuilder.fromServletMapping(request) .path("/accounts").build()
controller的鏈接

Spring MVC使用MvcUriComponentsBuilder為controller創建鏈接,例如由如下一個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賦值給從類的@RequestMapping繼承過來的查詢參數{hotel}。 MvcUriComponentsBuilder的另一個用處是可以mock一個測試,例如:

UriComponents uriComponents = MvcUriComponentsBuilder
    .fromMethodCall(on(BookingController.class).getBooking(21)).buildAndExpand(42); URI uri = uriComponents.encode().toUri();

上面的例子大多數情況下運行良好,但是也有不足,例如:可能會在request上下文外創建uri,或者是需要插入一個路徑前綴(比如測試的時候通過前綴測試,但是正式上線后直接是根(/))。對於這種情況可以使用靜態函數fromXxx這種進行處理:

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();
視圖中的鏈接

可以通過MvcUriComponentsBuilderfromMappingName在視圖(例如:JSP,Thymleaf,FreeMarker等)中構建指向controller的鏈接。 每個@RequestMapping的方法都會有一個名字,這個名字基於controller類名的大些字母加上‘#’號再加上方法名構成,例如,FooController類中的getFoo方法的名字就是FC#getFoo。當然這個可以通過修改HandlerMethodMappingNamingStrategy來定制其名字。默認策略同樣也會去查找@RequestMapping中設置名字的屬性,如果提供了,則會使用其設置的名字。 Spring JSP的tag庫提供了一個mvcUrl的方法,這個可以用來構建指向controller的方法。例如有如下controller:

@RequestMapping("/people/{id}/addresses") public class PersonAddressController { @RequestMapping("/{country}") public HttpEntity getAddress(@PathVariable String country) { ... } }

JSP中可以如下來構建指向其URI

<%@ taglib uri="http://www.springframework.org/tags" prefix="s" %> ... <a href="${s:mvcUrl('PAC#getAddress').arg(0,'US').buildAndExpand('123')}">Get Address</a>


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM