You need to enable JavaScript to run this app. Spring WebClient基于响应体非阻塞抛出自定义错误实现
优惠活动
大模型
产品
解决方案
定价
更多

Spring WebClient基于响应体非阻塞抛出自定义错误实现

Spring WebClient 非阻塞错误响应适配实现

核心实现逻辑

整个错误处理全程需要保持非阻塞特性,不能在onStatus回调中同步拉取响应体内容,必须依托WebClient自带的异步反序列化能力,完成响应体结构判断后再抛出对应异常,具体实现点:

  • 错误响应存在两种不同的结构,无法用单个POJO直接强转,因此先将错误响应体反序列化为通用的JsonNode结构,判断存在的字段后匹配对应错误类型
  • 所有解析、异常抛出的链路全部基于响应式流的异步回调完成,不调用任何block类阻塞方法
  • 两种结构匹配后,将提取到的错误文本、错误码封装为自定义业务异常抛出,由下游的全局异常处理器统一捕获处理

补全后的可运行代码

// 自定义业务异常,可根据自身项目规范调整字段
public static class BusinessApiException extends RuntimeException {
    private final int httpStatus;
    public BusinessApiException(int httpStatus, String message) {
        super(message);
        this.httpStatus = httpStatus;
    }
    // 可按需补全getter方法
}

public Mono<Response> webclient1(...) {
    return webClient.post().uri(createUserUri)
            .header(CONTENT_TYPE, APPLICATION_JSON)
            .body(Mono.just(request), Request.class)
            .retrieve()
            .onStatus(HttpStatus::isError, clientResponse -> {
                // 异步解析响应体为通用Json结构,全程非阻塞
                return clientResponse.bodyToMono(JsonNode.class)
                        .flatMap(errorNode -> {
                            // 匹配含error文本字段的错误结构
                            if (errorNode.has("error")) {
                                String errorMsg = errorNode.get("error").asText().trim();
                                return Mono.error(new BusinessApiException(
                                        clientResponse.statusCode().value(),
                                        errorMsg
                                ));
                            }
                            // 匹配含error_code错误码的错误结构
                            if (errorNode.has("error_code")) {
                                String errorCode = errorNode.get("error_code").asText();
                                return Mono.error(new BusinessApiException(
                                        clientResponse.statusCode().value(),
                                        errorCode
                                ));
                            }
                            // 兜底逻辑:未匹配到指定错误结构时抛出通用错误
                            return Mono.error(new BusinessApiException(
                                    clientResponse.statusCode().value(),
                                    "接口调用失败,HTTP状态码:" + clientResponse.statusCode()
                            ));
                        });
            })
            .bodyToMono(Response.class);
}

实现注意事项

  • 全程不使用block()方法拉取响应体:整个反序列化过程由WebClient内置的编解码线程异步完成,解析完成后直接将错误信号汇入响应式流,不会阻塞业务调用线程
  • 不需要手动缓存响应体:WebClient的bodyToMono会自动完成小体积错误响应的流读取,不存在响应流被提前消费的问题
  • 字段判断必须在异步解析的回调内完成:不能在onStatus的同步代码块里直接判断字段是否存在,因为此时响应体内容还未被异步拉取到内存中,强行判断会拿到空值
  • 自定义异常可根据项目的异常体系调整,只要能携带对应错误信息即可,无需依赖框架内置的WebClient异常类

内容的提问来源于stack exchange,提问作者salman irfan khandu

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.11.01 02:24:03