菜单

WebFlux 和响应式编程

相关源文件

本文档涵盖 Spring WebFlux 的响应式 HTTP 客户端功能,重点介绍 WebClient API 及其用于发出非阻塞 HTTP 请求的支持基础设施。该系统为 HTTP 通信提供了一种流畅、响应式的替代传统 RestTemplate 的方案。

有关服务器端响应式 Web 功能,请参阅 Spring MVC。有关客户端和服务器之间共享的 HTTP 抽象,请参阅 HTTP 抽象和 URI 处理

目的与范围

Spring WebFlux 的客户端功能围绕着 WebClient,一个支持以下功能的响应式 HTTP 客户端:

  • 使用响应式流(MonoFlux)的非阻塞 HTTP 请求
  • 用于构建包含请求头、Cookie 和请求体内容的流畅 API
  • 声明式错误处理和状态码处理
  • 与各种 HTTP 客户端实现(Reactor Netty、Jetty、HttpComponents、JDK)的集成
  • 通过模拟实现提供全面的测试支持

核心架构

WebFlux 客户端架构采用分层方法,明确分离了配置、请求构建、执行和响应处理。

来源: spring-webflux/src/main/java/org/springframework/web/reactive/function/client/WebClient.java1-398 spring-webflux/src/main/java/org/springframework/web/reactive/function/client/DefaultWebClient.java1-758 spring-webflux/src/main/java/org/springframework/web/reactive/function/client/DefaultWebClientBuilder.java1-380 spring-webflux/src/main/java/org/springframework/web/reactive/function/client/ExchangeFunctions.java1-166

WebClient 实现

WebClient 作为响应式 HTTP 请求的主要入口点,通过 DefaultWebClient 实现,并采用构建器模式进行配置。

来源: spring-webflux/src/main/java/org/springframework/web/reactive/function/client/WebClient.java147-166 spring-webflux/src/main/java/org/springframework/web/reactive/function/client/DefaultWebClient.java112-133 spring-webflux/src/main/java/org/springframework/web/reactive/function/client/DefaultWebClientBuilder.java302-325

请求构建过程

DefaultWebClient 实现了一个流畅的 API,其中每个 HTTP 方法都会返回一个请求规范,允许渐进式配置:

  1. URI 规范:使用 uri() 方法配置目标 URL
  2. 请求头配置:添加请求头、Cookie 和其他请求元数据
  3. 请求体配置:对于 POST/PUT/PATCH 请求,指定请求体
  4. 执行:选择使用 retrieve() 获取简单响应,或使用 exchangeTo*() 进行高级处理

[spring-webflux/src/main/java/org/springframework/web/reactive/function/client/DefaultWebClient.java207-531 中的 DefaultRequestBodyUriSpec 类处理渐进式请求构建,收集所有配置直至最终执行步骤。

交换函数和 HTTP 传输

ExchangeFunction 抽象处理实际的 HTTP 通信,而 ExchangeFunctions 为不同的传输实现提供了工厂方法。

来源: spring-webflux/src/main/java/org/springframework/web/reactive/function/client/ExchangeFunctions.java66-68 spring-webflux/src/main/java/org/springframework/web/reactive/function/client/ExchangeFunctions.java96-114 spring-webflux/src/main/java/org/springframework/web/reactive/function/client/DefaultWebClientBuilder.java327-340

[spring-webflux/src/main/java/org/springframework/web/reactive/function/client/ExchangeFunctions.java71-164 中的 DefaultExchangeFunction 处理:

  • 连接管理:委托给 ClientHttpConnector 实现
  • 请求日志记录:记录 HTTP 方法、URL 和可选的请求头
  • 响应日志记录:记录状态码和响应元数据
  • 错误处理:将传输层异常包装在 WebClientRequestException
  • 可观测性:与 Micrometer 集成以实现指标和跟踪

响应处理和错误处理

响应处理通过 ClientResponse 抽象及其默认实现 DefaultClientResponse 进行处理。

来源: spring-webflux/src/main/java/org/springframework/web/reactive/function/client/ClientResponse.java1-397 spring-webflux/src/main/java/org/springframework/web/reactive/function/client/DefaultClientResponse.java1-301 spring-webflux/src/main/java/org/springframework/web/reactive/function/client/WebClientResponseException.java1-525

状态码处理

[spring-webflux/src/main/java/org/springframework/web/reactive/function/client/DefaultWebClient.java534-737 中的 DefaultResponseSpec 类实现了一个全面的状态码处理系统:

状态码范围默认行为异常类型
1xx, 2xx, 3xx正常处理
4xx 客户端错误创建 WebClientResponseException特定状态子类
5xx 服务器错误创建 WebClientResponseException特定状态子类
未知代码创建 UnknownHttpStatusCodeExceptionUnknownHttpStatusCodeException

可以使用 onStatus() 方法注册自定义状态处理器,它们优先于默认处理器。系统按注册顺序处理处理器,默认处理器始终最后应用。

测试支持

Spring WebFlux 为响应式 HTTP 客户端提供了全面的测试基础设施,包括用于集成测试的模拟实现和包装类。

来源: spring-webflux/src/test/java/org/springframework/web/reactive/function/client/WebClientIntegrationTests.java1-1401 spring-webflux/src/main/java/org/springframework/web/reactive/function/client/support/ClientResponseWrapper.java1-208 spring-web/src/testFixtures/java/org/springframework/web/testfixture/http/client/reactive/MockClientHttpRequest.java1-169

模拟客户端配置

测试基础设施通过参数化测试支持各种 HTTP 客户端实现

MockClientHttpRequest 提供以下功能:

  • 请求体捕获:缓存请求体以进行测试断言
  • 自定义写入处理器:支持无限流和自定义处理
  • 请求头和 Cookie 检查:完全访问请求元数据
  • 字符串转换:通过 getBodyAsString() 轻松验证内容

来源: spring-webflux/src/test/java/org/springframework/web/reactive/function/client/WebClientIntegrationTests.java106-113 spring-web/src/testFixtures/java/org/springframework/web/testfixture/http/client/reactive/MockClientHttpRequest.java76-88