在使用Spring WebClient发起HTTP请求时,我们通常会很顺利地将2xx成功响应体转换为自定义的Java POJO,但遇到4xx、5xx这类错误响应时,默认的处理逻辑往往不会自动把错误响应体映射到我们定义的错误POJO上,导致无法便捷地获取错误信息。下面我们就一步步解决这个问题。

常见错误响应场景说明
假设我们调用的外部接口在出错时会返回如下格式的JSON响应:
{
"code": 400,
"message": "参数校验失败",
"detail": "用户ID不能为空"
}我们通常会定义对应的错误POJO类:
public class ErrorResponse {
private Integer code;
private String message;
private String detail;
// getter和setter方法
public Integer getCode() {
return code;
}
public void setCode(Integer code) {
this.code = code;
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
public String getDetail() {
return detail;
}
public void setDetail(String detail) {
this.detail = detail;
}
@Override
public String toString() {
return "ErrorResponse{code=" + code + ", message='" + message + "', detail='" + detail + "'}";
}
}默认WebClient的问题
如果我们直接使用默认的WebClient发送请求,遇到错误响应时会抛出WebClientResponseException,此时错误响应体的内容只会以字符串形式存在,不会自动转换为ErrorResponse对象,示例代码如下:
WebClient webClient = WebClient.create("http://ipipp.com");
try {
String result = webClient.get()
.uri("/test")
.retrieve()
.bodyToMono(String.class)
.block();
System.out.println(result);
} catch (WebClientResponseException e) {
// 此时e.getResponseBodyAsString()是JSON字符串,需要手动解析
System.out.println("错误响应体:" + e.getResponseBodyAsString());
}这种方式需要手动解析JSON字符串,不仅繁琐,还不符合我们统一使用POJO处理响应的习惯。
使用onStatus方法处理错误响应
WebClient的retrieve()方法提供了onStatus方法,我们可以指定特定状态码范围,自定义错误处理逻辑,将错误响应体转换为POJO:
WebClient webClient = WebClient.create("http://ipipp.com");
try {
String result = webClient.get()
.uri("/test")
.retrieve()
// 处理4xx和5xx的错误响应
.onStatus(HttpStatus::is4xxClientError, clientResponse ->
clientResponse.bodyToMono(ErrorResponse.class)
.flatMap(errorResponse -> Mono.error(new BusinessException(errorResponse)))
)
.onStatus(HttpStatus::is5xxServerError, clientResponse ->
clientResponse.bodyToMono(ErrorResponse.class)
.flatMap(errorResponse -> Mono.error(new BusinessException(errorResponse)))
)
.bodyToMono(String.class)
.block();
System.out.println("请求结果:" + result);
} catch (BusinessException e) {
System.out.println("业务异常:" + e.getErrorResponse());
}这里我们定义了自定义的业务异常BusinessException,构造函数接收ErrorResponse对象:
public class BusinessException extends RuntimeException {
private final ErrorResponse errorResponse;
public BusinessException(ErrorResponse errorResponse) {
super(errorResponse.getMessage());
this.errorResponse = errorResponse;
}
public ErrorResponse getErrorResponse() {
return errorResponse;
}
}使用ExchangeFilterFunction全局处理
如果项目中很多地方都需要处理错误响应转换,我们可以使用ExchangeFilterFunction实现全局的过滤处理,避免重复代码:
ExchangeFilterFunction errorHandlingFilter = ExchangeFilterFunction.ofResponseProcessor(clientResponse -> {
if (clientResponse.statusCode().is4xxClientError() || clientResponse.statusCode().is5xxServerError()) {
return clientResponse.bodyToMono(ErrorResponse.class)
.flatMap(errorResponse -> Mono.error(new BusinessException(errorResponse)))
.then(Mono.empty());
}
return Mono.just(clientResponse);
});
WebClient webClient = WebClient.builder()
.filter(errorHandlingFilter)
.baseUrl("http://ipipp.com")
.build();
try {
String result = webClient.get()
.uri("/test")
.retrieve()
.bodyToMono(String.class)
.block();
System.out.println("请求结果:" + result);
} catch (BusinessException e) {
System.out.println("业务异常:" + e.getErrorResponse());
}注意事项
- 确保错误POJO的字段和响应JSON的字段名称一致,或者使用
@JsonProperty注解指定映射关系。 - 如果错误响应体的格式不固定,可以先转换为
Map类型,再根据实际内容提取信息。 - 使用
block()方法时需要注意线程上下文,避免在响应式链中随意使用阻塞方法。
通过以上两种方式,我们就可以很方便地将Spring WebClient的错误响应体转换为Java POJO,统一错误处理逻辑,让代码更简洁易维护。
Spring_WebClient错误响应体转换Java_POJOWebClient异常处理响应体解析修改时间:2026-05-30 23:37:00