Spring Boot 5 WebFlux Mono调用外部API无法获取错误信息
嘿,这个问题我之前做项目时也踩过坑!默认情况下WebClient的retrieve()方法只要收到非2xx的状态码,就会直接抛出WebClientResponseException,这时候你确实没法直接拿到API返回的错误JSON。别担心,下面给你几种实用的解决办法:
方法1:用
onStatus自定义错误拦截 你可以通过onStatus方法针对特定状态码(比如所有非2xx)拦截响应,手动解析返回的错误体:
webClient.post() .uri("你的外部API地址") .bodyValue(请求体对象) .retrieve() // 拦截所有非2xx的状态码 .onStatus(status -> !status.is2xxSuccessful(), clientResponse -> { // 将错误响应体解析为自定义的ErrorResponse类 return clientResponse.bodyToMono(ErrorResponse.class) .flatMap(errorBody -> { // 把错误信息包装成自定义异常抛出,方便后续处理 return Mono.error(new CustomApiException( errorBody.getError().getMessage(), errorBody.getError().getStatusCode() )); }); }) .bodyToMono(你的成功响应类型.class) .subscribe( successResult -> { /* 处理正常返回的业务逻辑 */ }, error -> { if (error instanceof CustomApiException) { CustomApiException apiError = (CustomApiException) error; System.out.println("API错误状态码:" + apiError.getStatusCode()); System.out.println("API错误详情:" + apiError.getMessage()); } } );
首先你需要创建对应API错误结构的实体类:
// 完全匹配API返回的错误JSON结构 public class ErrorResponse { private ErrorDetail error; // getter、setter 省略 public static class ErrorDetail { private int statusCode; private String name; private String message; // getter、setter 省略 } }
再定义一个自定义异常用来携带错误信息:
public class CustomApiException extends RuntimeException { private int statusCode; public CustomApiException(String message, int statusCode) { super(message); this.statusCode = statusCode; } // getter 省略 }
方法2:用
exchangeToMono统一处理所有响应 如果想更灵活地控制成功和错误分支的逻辑,exchangeToMono会是更好的选择——它不会自动抛出异常,你可以自己判断状态码:
webClient.post() .uri("你的外部API地址") .bodyValue(请求体对象) .exchangeToMono(clientResponse -> { if (clientResponse.statusCode().is2xxSuccessful()) { // 状态码正常,解析成功响应体 return clientResponse.bodyToMono(你的成功响应类型.class); } else { // 状态码异常,解析错误响应体并抛出自定义异常 return clientResponse.bodyToMono(ErrorResponse.class) .flatMap(errorBody -> Mono.error(new CustomApiException( errorBody.getError().getMessage(), errorBody.getError().getStatusCode() ))); } }) .subscribe( successResult -> { /* 成功逻辑 */ }, error -> { if (error instanceof CustomApiException) { CustomApiException apiError = (CustomApiException) error; // 这里就能拿到完整的错误详情了 System.out.println("错误信息:" + apiError.getMessage()); } } );
额外小技巧:从默认异常中提取错误体
如果你不想改动太多现有代码,也可以直接捕获WebClientResponseException,然后从异常中提取响应体:
webClient.post() .uri("你的外部API地址") .bodyValue(请求体对象) .retrieve() .bodyToMono(你的成功响应类型.class) .subscribe( successResult -> { /* 成功逻辑 */ }, error -> { if (error instanceof WebClientResponseException) { WebClientResponseException ex = (WebClientResponseException) error; // 获取错误体字符串 String errorBodyStr = ex.getResponseBodyAsString(); // 用ObjectMapper转成ErrorResponse对象 ObjectMapper mapper = new ObjectMapper(); try { ErrorResponse errorResponse = mapper.readValue(errorBodyStr, ErrorResponse.class); System.out.println("API返回的错误详情:" + errorResponse.getError().getMessage()); } catch (JsonProcessingException e) { e.printStackTrace(); } } } );
个人更推荐前两种方法,代码结构更清晰,也方便后续统一处理异常。
内容的提问来源于stack exchange,提问作者Mohale
相关产品推荐
相关产品推荐

