Spring WebClient中ExchangeStrategies与wiretap日志方案对比及实践疑问
WebClient调试日志:wiretap与ExchangeStrategies方案对比与实践
我正在使用Spring WebClient,为满足调试需求探索启用详细日志的方法,目前重点关注ExchangeStrategies和wiretap两种方案,已有的配置细节如下:
一、已配置的日志方案
1. wiretap日志配置
我通过Netty的wiretap功能记录HTTP请求和响应的网络级数据,配置代码如下:
HttpClient httpClient = HttpClient.create() .wiretap("reactor.netty.http.client.HttpClient", LogLevel.DEBUG, AdvancedByteBufFormat.TEXTUAL); WebClient webClient = WebClient.builder() .clientConnector(new ReactorClientHttpConnector(httpClient)) .build();
该方案会在网络层级记录请求头、请求体、响应体、HTTP状态码等细节。
2. ExchangeStrategies日志配置
另外,我通过自定义ExchangeStrategies启用序列化/反序列化过程的日志,配置代码如下:
ExchangeStrategies strategies = ExchangeStrategies.builder() .codecs(configurer -> configurer.defaultCodecs().maxInMemorySize(1024 * 1024 * 50)) .build(); strategies.messageWriters().stream() .filter(LoggingCodecSupport.class::isInstance) .forEach(writer -> ((LoggingCodecSupport) writer).setEnableLoggingRequestDetails(true));
该方案聚焦于记录请求/响应体与对象之间转换过程的细节。
二、技术问题与解答
1. 两种日志方案的功能差异是什么?
- wiretap:属于Reactor Netty层面的日志,记录的是网络传输层面的原始数据——也就是从客户端发出、到服务端接收,以及服务端返回、客户端接收的完整HTTP报文内容,包括原始的请求头、请求体(序列化后的字节流转文本)、响应头、响应体、状态码等,完全是网络交互的真实数据,不涉及Spring WebClient的序列化/反序列化逻辑。
- ExchangeStrategies:属于Spring WebFlux层面的日志,聚焦于对象与HTTP报文之间的转换过程——比如把Java对象序列化为JSON/XML请求体时的原始对象内容、序列化后的文本,或者把响应体文本反序列化为Java对象时的原始响应文本、转换后的对象内容,只关注序列化/反序列化环节的细节,不涉及网络传输的底层细节(比如TCP握手、分包等)。
2. 各自适合的场景?
- 优先用wiretap的场景:
- 需要排查网络通信问题,比如请求是否真的发送出去、服务端返回的原始报文是否符合预期、是否存在请求头被篡改、响应体截断等网络层面的问题。
- 调试第三方API对接时,需要确认发送的请求和收到的响应与API文档是否完全一致。
- 优先用ExchangeStrategies的场景:
- 排查序列化/反序列化错误,比如Java对象无法正确序列化为请求体、响应体无法反序列化为目标对象(比如字段不匹配、类型转换错误)。
- 需要确认对象转换前后的内容是否一致,比如验证序列化后的JSON是否和对象字段完全对应。
3. 如何同时记录两种日志?
只需要将两种配置结合使用即可,步骤如下:
- 保留wiretap的HttpClient配置,确保网络级数据被记录;
- 把自定义的ExchangeStrategies配置到WebClient中,确保序列化/反序列化过程被记录;
完整配置示例:
// 1. 配置wiretap HttpClient httpClient = HttpClient.create() .wiretap("reactor.netty.http.client.HttpClient", LogLevel.DEBUG, AdvancedByteBufFormat.TEXTUAL); // 2. 配置ExchangeStrategies ExchangeStrategies strategies = ExchangeStrategies.builder() .codecs(configurer -> configurer.defaultCodecs().maxInMemorySize(1024 * 1024 * 50)) .build(); strategies.messageWriters().stream() .filter(LoggingCodecSupport.class::isInstance) .forEach(writer -> ((LoggingCodecSupport) writer).setEnableLoggingRequestDetails(true)); // 3. 构建WebClient时同时注入两者 WebClient webClient = WebClient.builder() .clientConnector(new ReactorClientHttpConnector(httpClient)) .exchangeStrategies(strategies) .build();
同时,需要确保日志配置中对应的Logger级别为DEBUG:
- 对于wiretap,确保
reactor.netty.http.client.HttpClient的日志级别是DEBUG; - 对于ExchangeStrategies,确保
org.springframework.web.reactive.function.client相关Logger的级别是DEBUG(具体是负责编码的类,比如org.springframework.http.codec.json.Jackson2JsonEncoder等,一般开启包级别的DEBUG即可)。
环境信息
- Spring Boot: 3.3.2
- Spring WebFlux: 3.3.2
- Reactor Netty: 1.2.6
- JDK: 17
内容的提问来源于stack exchange,提问作者백현명
相关产品推荐
相关产品推荐

