1. 简介
本文将深入探讨如何在 Spring WebClient 中一次性设置多个请求头。WebClient 是 Spring WebFlux 框架的核心组件,支持同步和异步 HTTP 请求。我们将先解析 WebClient 的请求头处理机制,再通过代码示例演示三种批量设置请求头的实用方案。
2. WebClient 的请求头处理机制
HTTP 请求头本质是元数据,承载认证信息、内容类型、版本号等关键数据。在 WebClient 中,HttpHeaders
类负责管理这些请求头,它实现了 MultiValueMap<String, String>
接口,允许单个请求头键对应多个值(如 Accept
头)。这种设计完美支持需要多值请求头的场景。
⚠️ 关键点:HttpHeaders 是 Spring 专门为 HTTP 请求/响应头设计的类,不是普通的 Map 实现。
3. 批量设置请求头的三种方案
根据使用场景,我们可以选择为单个请求设置、全局默认设置或动态修改请求头。下面通过代码示例逐一说明。
3.1. 为单个请求设置请求头
当不同接口需要不同请求头时,直接在请求中设置最简单粗暴。以下测试用例演示了如何添加两个自定义请求头,并通过 MockWebServer 验证请求头是否正确发送:
@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>)
方法,使用 Lambda 表达式操作 HttpHeaders 实例。这种函数式接口设计让请求头修改变得极其灵活。
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());
注册过滤器到 WebClient:
WebClient client = WebClient.builder()
.baseUrl(mockWebServer.url("/").toString())
.filter(dynamicHeadersFilter)
.build();
✅ 高级技巧:可叠加多个过滤器实现复杂逻辑(如认证+日志+签名),且过滤器执行顺序与注册顺序一致。
4. 总结
Spring WebClient 提供了三种灵活的请求头管理方案:
- 单个请求设置:适用于接口差异化的场景
- 全局默认设置:减少重复代码,保证一致性
- 动态过滤器:满足运行时修改需求
根据实际需求选择合适方案,既能提升开发效率,又能避免请求头配置混乱。完整示例代码可在 GitHub 获取。