URI 連結

本節描述了 Spring Framework 中可用於準備 URI 的各種選項。

UriComponents

Spring MVC 和 Spring WebFlux

UriComponentsBuilder 幫助從帶有變數的 URI 模板構建 URI,如以下示例所示

  • Java

  • Kotlin

UriComponents uriComponents = UriComponentsBuilder
		.fromUriString("https://example.com/hotels/{hotel}") (1)
		.queryParam("q", "{q}") (2)
		.encode() (3)
		.build(); (4)

URI uri = uriComponents.expand("Westin", "123").toUri(); (5)
1 帶有 URI 模板的靜態工廠方法。
2 新增或替換 URI 元件。
3 請求對 URI 模板和 URI 變數進行編碼。
4 構建 UriComponents
5 展開變數並獲取 URI
val uriComponents = UriComponentsBuilder
		.fromUriString("https://example.com/hotels/{hotel}") (1)
		.queryParam("q", "{q}") (2)
		.encode() (3)
		.build() (4)

val uri = uriComponents.expand("Westin", "123").toUri() (5)
1 帶有 URI 模板的靜態工廠方法。
2 新增或替換 URI 元件。
3 請求對 URI 模板和 URI 變數進行編碼。
4 構建 UriComponents
5 展開變數並獲取 URI

前面的示例可以合併為一個鏈,並使用 buildAndExpand 縮短,如以下示例所示

  • Java

  • Kotlin

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

您可以透過直接轉到 URI(這暗示了編碼)來進一步縮短它,如以下示例所示

  • Java

  • Kotlin

URI uri = UriComponentsBuilder
		.fromUriString("https://example.com/hotels/{hotel}")
		.queryParam("q", "{q}")
		.build("Westin", "123");
val uri = UriComponentsBuilder
		.fromUriString("https://example.com/hotels/{hotel}")
		.queryParam("q", "{q}")
		.build("Westin", "123")

您還可以使用完整的 URI 模板進一步縮短它,如以下示例所示

  • Java

  • Kotlin

URI uri = UriComponentsBuilder
		.fromUriString("https://example.com/hotels/{hotel}?q={q}")
		.build("Westin", "123");
val uri = UriComponentsBuilder
		.fromUriString("https://example.com/hotels/{hotel}?q={q}")
		.build("Westin", "123")

UriBuilder

Spring MVC 和 Spring WebFlux

UriComponentsBuilder 實現了 UriBuilder。您可以反過來使用 UriBuilderFactory 建立 UriBuilderUriBuilderFactoryUriBuilder 共同提供了一種可插拔的機制,用於根據共享配置(例如基本 URL、編碼偏好和其他詳細資訊)從 URI 模板構建 URI。

您可以配置 RestTemplateWebClientUriBuilderFactory 以自定義 URI 的準備。DefaultUriBuilderFactoryUriBuilderFactory 的預設實現,它在內部使用 UriComponentsBuilder 並公開共享配置選項。

以下示例展示瞭如何配置 RestTemplate

  • Java

  • Kotlin

// 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

val baseUrl = "https://example.org"
val factory = DefaultUriBuilderFactory(baseUrl)
factory.encodingMode = EncodingMode.TEMPLATE_AND_VALUES

val restTemplate = RestTemplate()
restTemplate.uriTemplateHandler = factory

以下示例配置 WebClient

  • Java

  • Kotlin

// 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();
// import org.springframework.web.util.DefaultUriBuilderFactory.EncodingMode

val baseUrl = "https://example.org"
val factory = DefaultUriBuilderFactory(baseUrl)
factory.encodingMode = EncodingMode.TEMPLATE_AND_VALUES

val client = WebClient.builder().uriBuilderFactory(factory).build()

此外,您還可以直接使用 DefaultUriBuilderFactory。它類似於使用 UriComponentsBuilder,但它不是靜態工廠方法,而是實際的例項,它包含配置和偏好,如以下示例所示

  • Java

  • Kotlin

String baseUrl = "https://example.com";
DefaultUriBuilderFactory uriBuilderFactory = new DefaultUriBuilderFactory(baseUrl);

URI uri = uriBuilderFactory.uriString("/hotels/{hotel}")
		.queryParam("q", "{q}")
		.build("Westin", "123");
val baseUrl = "https://example.com"
val uriBuilderFactory = DefaultUriBuilderFactory(baseUrl)

val uri = uriBuilderFactory.uriString("/hotels/{hotel}")
		.queryParam("q", "{q}")
		.build("Westin", "123")

URI 解析

Spring MVC 和 Spring WebFlux

UriComponentsBuilder 支援兩種 URI 解析器型別

  1. RFC 解析器——此解析器型別要求 URI 字串符合 RFC 3986 語法,並將偏離此語法的行為視為非法。

  2. WhatWG 解析器——此解析器基於 WhatWG URL Living standard 中的 URL 解析演算法。它對各種意外輸入情況提供了寬鬆的處理。瀏覽器實現此功能是為了寬鬆處理使用者輸入的 URL。有關更多詳細資訊,請參閱 URL Living Standard 和 URL 解析測試用例

預設情況下,RestClientWebClientRestTemplate 使用 RFC 解析器型別,並期望應用程式提供符合 RFC 語法的 URL 模板。要更改此設定,您可以自定義任何客戶端上的 UriBuilderFactory

應用程式和框架可能會進一步依賴 UriComponentsBuilder 來解析使用者提供的 URL,以檢查並可能驗證 URI 元件,例如 scheme、host、port、path 和 query。這些元件可以決定使用 WhatWG 解析器型別,以便更寬鬆地處理 URL,並在重定向到輸入 URL 或將其包含在對瀏覽器的響應中時,與瀏覽器解析 URI 的方式保持一致。

URI 編碼

Spring MVC 和 Spring WebFlux

UriComponentsBuilder 在兩個級別公開編碼選項

這兩個選項都將非 ASCII 和非法字元替換為轉義八位位元組。但是,第一個選項還會替換 URI 變數中出現的具有保留含義的字元。

考慮“;”,它在路徑中是合法的,但具有保留含義。第一個選項將 URI 變數中的“;”替換為“%3B”,但在 URI 模板中不替換。相比之下,第二個選項從不替換“;”,因為它在路徑中是合法字元。

在大多數情況下,第一個選項可能會給出預期的結果,因為它將 URI 變數視為不透明資料進行完全編碼,而如果 URI 變數確實有意包含保留字元,則第二個選項很有用。當根本不展開 URI 變數時,第二個選項也很有用,因為它也會編碼任何偶然看起來像 URI 變數的東西。

以下示例使用第一個選項

  • Java

  • Kotlin

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"
val 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"

您可以透過直接轉到 URI(這暗示了編碼)來縮短前面的示例,如以下示例所示

  • Java

  • Kotlin

URI uri = UriComponentsBuilder.fromPath("/hotel list/{city}")
		.queryParam("q", "{q}")
		.build("New York", "foo+bar");
val uri = UriComponentsBuilder.fromPath("/hotel list/{city}")
		.queryParam("q", "{q}")
		.build("New York", "foo+bar")

您還可以使用完整的 URI 模板進一步縮短它,如以下示例所示

  • Java

  • Kotlin

URI uri = UriComponentsBuilder.fromUriString("/hotel list/{city}?q={q}")
		.build("New York", "foo+bar");
val uri = UriComponentsBuilder.fromUriString("/hotel list/{city}?q={q}")
		.build("New York", "foo+bar")

WebClientRestTemplate 透過 UriBuilderFactory 策略在內部擴充套件和編碼 URI 模板。兩者都可以配置自定義策略,如以下示例所示

  • Java

  • Kotlin

String baseUrl = "https://example.com";
DefaultUriBuilderFactory factory = new DefaultUriBuilderFactory(baseUrl)
factory.setEncodingMode(EncodingMode.TEMPLATE_AND_VALUES);

// Customize the RestTemplate..
RestTemplate restTemplate = new RestTemplate();
restTemplate.setUriTemplateHandler(factory);

// Customize the WebClient..
WebClient client = WebClient.builder().uriBuilderFactory(factory).build();
val baseUrl = "https://example.com"
val factory = DefaultUriBuilderFactory(baseUrl).apply {
	encodingMode = EncodingMode.TEMPLATE_AND_VALUES
}

// Customize the RestTemplate..
val restTemplate = RestTemplate().apply {
	uriTemplateHandler = factory
}

// Customize the WebClient..
val client = WebClient.builder().uriBuilderFactory(factory).build()

DefaultUriBuilderFactory 實現內部使用 UriComponentsBuilder 來擴充套件和編碼 URI 模板。作為工廠,它提供了一個配置編碼方法的單一位置,基於以下編碼模式之一

  • TEMPLATE_AND_VALUES:使用 UriComponentsBuilder#encode(),對應於前面列表中的第一個選項,預編碼 URI 模板並在展開時嚴格編碼 URI 變數。

  • VALUES_ONLY:不編碼 URI 模板,而是透過 UriUtils#encodeUriVariables 對 URI 變數應用嚴格編碼,然後將其展開到模板中。

  • URI_COMPONENT:使用 UriComponents#encode(),對應於前面列表中的第二個選項,在 URI 變數展開之後編碼 URI 元件值。

  • NONE:不應用任何編碼。

出於歷史原因和向後相容性,RestTemplate 被設定為 EncodingMode.URI_COMPONENTWebClient 依賴於 DefaultUriBuilderFactory 中的預設值,該值在 5.0.x 中從 EncodingMode.URI_COMPONENT 更改為 5.1 中的 EncodingMode.TEMPLATE_AND_VALUES

© . This site is unofficial and not affiliated with VMware.