You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Webflux Pass-Through Http Error:如何将响应异常冒泡传递并携带信息?

如何用ExchangeFilterFunction冒泡传递包含响应体和HTTP状态码的WebClient异常

我明白你现在的痛点:想用WebClient的ExchangeFilterFunction把请求中收到的异常(包含响应体和状态码)冒泡传递,但之前的尝试要么捕获不到错误,要么没法把响应体内容塞进异常里。咱们一步步来解决这个问题。

先分析你之前代码的问题

  1. 第一个过滤器不生效的原因:WebClient默认不会把HTTP错误状态码(比如4xx、5xx)转化为Mono/Flux的错误信号,只会返回一个带有错误状态的ClientResponse。所以你的onErrorMap(MyError.class, ...)根本不会触发——因为没有错误信号产生。

  2. 第二个代码的问题:你尝试在错误状态时返回一个包含Flux.error()的ClientResponse,但这种方式下游只有在调用bodyToMono()之类的方法时才会触发错误,而且你没法把实际的响应体内容(比如MyError的字段)传递进去,只是抛出了一个固定消息的RuntimeException。

正确的实现方案

我们需要做的是:检查响应状态码,如果是错误状态,就读取响应体到你的MyError类,然后主动抛出这个异常,这样下游就能捕获到包含完整信息的异常了。

1. 完善你的ExchangeFilterFunction实现

public class MyExchangeFilterFunction implements ExchangeFilterFunction {

    @Override
    public Mono<ClientResponse> filter(ClientRequest request, ExchangeFunction next) {
        return next.exchange(request)
                .flatMap(clientResponse -> {
                    // 判断是否是HTTP错误状态码
                    if (clientResponse.statusCode().isError()) {
                        // 读取响应体到MyError对象,然后抛出异常
                        return clientResponse.bodyToMono(MyError.class)
                                .flatMap(myError -> {
                                    // 可以在这里补充一些额外信息,比如请求路径
                                    myError.setPath(request.url().getPath());
                                    return Mono.error(myError);
                                })
                                // 处理读取响应体失败的情况
                                .onErrorResume(e -> Mono.error(new RuntimeException("Failed to read error response body", e)));
                    } else {
                        // 正常响应直接返回
                        return Mono.just(clientResponse);
                    }
                });
    }
}

2. 过滤器注册(和你之前的方式一致,确保正确添加)

WebClient webClient = WebClient.builder()
        .filter(new MyExchangeFilterFunction())
        // 其他配置比如baseUrl、codecs等
        .build();

3. 下游使用时捕获异常

现在当你用这个WebClient发起请求时,一旦收到错误状态码,过滤器就会抛出MyError异常,你可以在下游捕获并处理:

webClient.get()
        .uri("/some-api")
        .retrieve()
        .bodyToMono(YourResponse.class)
        .onErrorMap(MyError.class, error -> {
            // 这里可以拿到error里的status、message、path等信息
            System.err.println("HTTP Error: " + error.getStatus() + ", Message: " + error.getMessage());
            // 可以选择重新包装异常或者直接抛出
            return error;
        })
        .subscribe();

关键说明

  • 为什么用flatMap而不是map?因为读取响应体是异步操作(bodyToMono()返回Mono<MyError>),所以需要用flatMap来处理异步流。
  • 一定要处理读取响应体失败的情况(onErrorResume),避免因为响应体格式不符合MyError导致整个流被中断。

内容的提问来源于stack exchange,提问作者Flavouski

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.27 07:21:07