RestTemplate返回200/201状态触发handleResponse/handleError问题排查
问题根因
- 首先纠正认知偏差:RestTemplate的
handleResponse(URI url, HttpMethod method, ClientHttpResponse response)方法是所有HTTP请求响应的必经流程,并非只有响应异常时才会执行。该方法内部会调用绑定的ResponseErrorHandler的hasError方法判定响应是否为错误,只有hasError返回true时,才会继续调用handleError方法执行错误处理逻辑。因此返回200 Success时进入该方法、流转到自定义ErrorHandler类是符合框架设计的正常流程,此时因为hasError返回false,不会触发后续错误抛出逻辑。 - 返回201 Created时触发异常的核心原因是自定义错误处理器判断逻辑有误:
实现的hasError方法将「状态码不等于HttpStatus.OK」作为错误判定条件,这意味着除了200之外的所有状态码——包括HTTP标准中属于成功响应范畴的201 Created、204 No Content等2xx状态码,都会被判定为错误响应,进而进入handleError方法。而handleError的switch分支没有覆盖201状态,最终走default分支抛出了INTERNAL_SERVER_ERROR对应的业务异常。
解决方案
根据业务语义选择对应修改方式即可:
- 方案1(符合HTTP标准规范,推荐):将所有2xx类状态码都判定为成功响应,修改
hasError逻辑:
@Override public boolean hasError(ClientHttpResponse clientHttpResponse) throws IOException { HttpStatus statusCode = clientHttpResponse.getStatusCode(); // 非2xx范围的状态码才判定为错误 return !statusCode.is2xxSuccessful(); }
- 方案2(适配仅200算成功的特殊业务场景):保留现有
hasError判断逻辑,在handleError的switch分支中补全所有非200但需要特殊处理的状态码,不要让其走default分支抛出500错误,例如补充201的对应处理逻辑:
// 其他已有分支不变 case CREATED: // 201 Created // 根据业务需求实现对应逻辑,例如直接返回不抛异常、或抛出匹配的业务异常 break; default: throw new BusinessException(errMessage, ErrorResponse.INTERNAL_SERVER_ERROR);
额外优化点:外层调用restTemplate.exchange时的catch块存在冗余逻辑,错误状态码的判断、对应BusinessException的抛出已经在自定义ErrorHandler中实现,外层不需要重复判断状态码,直接捕获抛出的BusinessException做后续业务处理即可。
内容的提问来源于stack exchange,提问作者Tech_sharma
相关产品推荐
相关产品推荐

