1. 簡介
本教程將介紹如何同時設置多個標題,重點講解 Spring WebClient 的用法。
WebClient 是 Spring WebFlux 中的一個類,簡單來説,它允許你進行同步和異步的 HTTP 請求。 我們首先將瞭解 WebClient 如何處理請求頭,然後通過代碼示例探索同時設置多個請求頭的方法。
2. WebClient 如何處理 Headers
在 HTTP 請求中,Headers 通常用作元數據。它們攜帶諸如身份驗證詳細信息、內容類型、版本等信息。
**在 WebClient 中,<a href="https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/http/HttpHeaders.html">HttpHeaders</a> 類負責管理 Headers。** 它是一個 Spring 框架類,專門設計用於表示請求和響應 Headers。它實現了MultiValueMap<String, String>, 允許單個 Header 鍵具有多個值。
這提供了靈活性,用於需要多個值的 Header,例如 Accept。
3. 在 WebClient 中設置多個請求頭
有幾種方法可以為請求添加請求頭。 根據具體用例,我們可以為單個請求設置請求頭,為整個 WebClient 實例定義全局請求頭,或在運行時動態修改它們。
讓我們通過代碼示例來探索這些方法。
3.1. 為單個請求設置標頭
當標頭與單個請求相關聯且因端點而異時,最直接的方法是在請求中直接設置它們。
在以下示例中,我們創建了一個簡單的測試,其中實例化了 WebClient,向請求添加兩個標頭,並斷言請求已使用這些標頭髮送。我們還使用了 okhttp3 庫中的 MockWebServer 來模擬服務器響應並驗證 WebClient 的行為:
@Test
public void givenRequestWithHeaders_whenSendingRequest_thenAssertHeadersAreSent() throws Exception {
mockWebServer.enqueue(new MockResponse().setResponseCode(HttpStatus.OK.value()));
WebClient client = WebClient.builder()
.baseUrl(mockWebServer.url("/").toString())
.build();
ResponseEntity<Void> response = client.get()
.headers(headers -> {
headers.put("X-Request-Id", Collections.singletonList(RANDOM_UUID));
headers.put("Custom-Header", Collections.singletonList("CustomValue"));
})
.retrieve()
.toBodilessEntity()
.block();
assertNotNull(response);
assertEquals(HttpStatusCode.valueOf(HttpStatus.OK.value()), response.getStatusCode());
RecordedRequest recordedRequest = mockWebServer.takeRequest();
assertEquals(RANDOM_UUID, recordedRequest.getHeader("X-Request-Id"));
assertEquals("CustomValue", recordedRequest.getHeader("Custom-Header"));
}此示例使用 headers(Consumer<HttpHeaders> headersConsumer) 方法,該方法來自 WebClient 類。
正如我們之前所提到的,WebClient 依賴於 HttpHeaders,這些配置使用本上下文中的 Consumer 函數接口完成。
這種設置允許我們通過傳遞一個操作 HttpHeaders 實例的 lambda 表達式來修改請求頭。
3.2. 全局設置默認請求頭
在某些場景下,我們可能需要定義全局請求頭。這些請求頭在全球範圍內進行配置,並且會自動添加到使用該客户端實例的所有請求中。這種配置有助於我們保持一致性並減少重複。
我們始終可以覆蓋全局請求頭,使用請求特定的請求頭,因為它們僅作為基線。 唯一的區別在於,我們在構建 WebClient 時添加它們:
WebClient client = WebClient.builder()
.baseUrl(mockWebServer.url("/").toString())
.defaultHeaders(headers -> {
headers.put("X-Request-Id", Collections.singletonList(RANDOM_UUID));
headers.put("Custom-Header", Collections.singletonList("CustomValue"));
})
.build();3.3. 使用 ExchangeFilterFunction 動態修改請求頭
在某些情況下,我們可能需要在運行時動態設置或修改請求頭。對於此類情況,可以使用 ExchangeFilterFunction 類:
ExchangeFilterFunction dynamicHeadersFilter = (request, next) -> next.exchange(ClientRequest.from(request)
.headers(headers -> {
headers.put("X-Request-Id", Collections.singletonList(RANDOM_UUID));
headers.put("Custom-Header", Collections.singletonList("CustomValue"));
})
.build());在構建 ExchangeFilterFunction 實例後,我們會在實例化時將其註冊到 WebClient 中:
WebClient client = WebClient.builder()
.baseUrl(mockWebServer.url("/").toString())
.filter(dynamicHeadersFilter)
.build();此外,我們還可以為單個 WebClient 堆疊多個過濾器函數實例。
4. 結論
本文介紹了 Spring WebClient 如何處理 HTTP 頭部,並探討了設置多個頭部的方法。無論是在單個請求中、全局請求中,還是在運行時動態設置,WebClient 都提供了一種簡單而靈活的方式,以一致且清晰的方式管理頭部。