如何在Spring WebFlux应用中仅记录Spring HttpClient的HTTP 400错误响应
处理Spring WebFlux中WebClient返回HTTP 400时的响应记录
要实现WebClient调用目标URL返回HTTP 400状态码时记录响应内容,你可以通过以下方式修改现有代码,核心思路是在处理ClientResponse时,先判断状态码,缓存响应体后完成日志记录,再继续构建返回给客户端的响应:
修改后的完整代码
import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.web.reactive.function.client.ClientResponse; import org.springframework.web.reactive.function.server.ServerRequest; import org.springframework.web.reactive.function.server.ServerResponse; import org.springframework.web.reactive.function.client.WebClient; import reactor.core.publisher.Mono; public class UrlHandler { // 初始化SLF4J日志实例 private static final Logger log = LoggerFactory.getLogger(UrlHandler.class); private WebClient webClient; public UrlHandler(WebClient webClient) { this.webClient = webClient; } public Mono<ServerResponse> fetch(ServerRequest request) { String u = request.queryParam("u").get(); return webClient .get() .uri(u) .exchangeToMono(UrlHandler::fromClientResponse) .retry(1); } private static Mono<ServerResponse> fromClientResponse(final ClientResponse clientResponse) { // 缓存响应体,确保可多次订阅(日志+返回客户端) Mono<String> responseBodyMono = clientResponse.bodyToMono(String.class).cache(); // 仅当状态码为400时记录响应 Mono<Void> log400Mono = Mono.empty(); if (clientResponse.statusCode().value() == 400) { log400Mono = responseBodyMono .doOnNext(body -> log.error("Received HTTP 400 response. Headers: {}, Body: {}", clientResponse.headers().asHttpHeaders(), body)) // 处理读取响应体时的异常,避免流中断 .onErrorResume(e -> { log.error("Failed to read HTTP 400 response body", e); return Mono.empty(); }) .then(); } // 先执行日志记录,再构建返回给客户端的响应 return log400Mono.then(Mono.defer(() -> ServerResponse.status(clientResponse.statusCode()) .headers(headerConsumer -> clientResponse.headers().asHttpHeaders().forEach(headerConsumer::addAll)) .body(responseBodyMono, String.class) )); } }
关键实现细节
- 响应体缓存:使用
cache()操作符缓存响应体Mono,解决反应式流中响应体只能读取一次的问题,确保日志记录和返回客户端都能获取到响应内容。 - 条件日志触发:通过判断
clientResponse.statusCode().value() == 400精准触发日志逻辑,避免不必要的日志记录。 - 反应式流程顺序:用
log400Mono.then(...)保证日志记录逻辑先执行,再构建并返回响应,符合反应式编程的异步流特性。 - 异常容错:添加
onErrorResume处理读取响应体时的异常,防止日志逻辑的异常导致整个请求处理流中断。
内容的提问来源于stack exchange,提问作者pragnesh
相关产品推荐
相关产品推荐

