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

Spring Boot服务调用中错误状态码ResponseEntity引发调用方异常咨询

问题根源

这其实是RestTemplate的默认行为搞的鬼:当被调用服务返回4xx/5xx这类错误状态码时,RestTemplate不会直接把带错误状态的ResponseEntity返回给你,而是会抛出对应的异常——4xx错误抛HttpClientErrorException,5xx错误抛HttpServerErrorException,所以你的调用方代码才会总是进入异常分支。

解决方案

下面给你几种实用的处理方式,按需选择就行:

1. 直接捕获异常提取错误信息

最省事的方式就是在调用代码里把这些异常接住,从异常对象里掏出来你需要的错误响应内容、状态码和headers:

ResponseEntity<String> responseEntity;
try {
    responseEntity = restTemplate.postForEntity(url, entity, String.class);
    // 处理正常的2xx响应逻辑
} catch (HttpServerErrorException e) {
    // 专门处理5xx错误,比如你遇到的INTERNAL_SERVER_ERROR
    String errorJson = e.getResponseBodyAsString(); // 拿到被调用方返回的jsonString
    HttpStatus errorStatus = e.getStatusCode();
    HttpHeaders errorHeaders = e.getResponseHeaders();
    // 这里就可以解析errorJson做后续处理了
} catch (HttpClientErrorException e) {
    // 处理4xx错误,比如400参数错误、404资源不存在等
    String errorJson = e.getResponseBodyAsString();
    // 按需处理
} catch (RestClientException e) {
    // 兜底捕获其他RestClient相关异常
    e.printStackTrace();
}

2. 自定义ErrorHandler让RestTemplate不抛异常

如果你希望不管响应状态是成功还是失败,RestTemplate都直接返回ResponseEntity而不炸锅,可以自定义一个ResponseErrorHandler来覆盖默认行为:

第一步:写自定义ErrorHandler类

import org.springframework.http.HttpStatus;
import org.springframework.http.client.ClientHttpResponse;
import org.springframework.web.client.DefaultResponseErrorHandler;

import java.io.IOException;

public class NoThrowErrorHandler extends DefaultResponseErrorHandler {
    @Override
    public void handleError(ClientHttpResponse response) throws IOException {
        // 这里啥都不做(或者只记录个日志),就是不抛出异常
        // 比如加个日志:log.warn("收到错误响应: {} - {}", response.getStatusCode(), response.getStatusText());
    }

    @Override
    public boolean hasError(ClientHttpResponse response) throws IOException {
        // 保持默认的错误判断逻辑(4xx/5xx算错误),但就是不抛异常
        HttpStatus statusCode = HttpStatus.resolve(response.getRawStatusCode());
        return statusCode != null && statusCode.isError();
    }
}

第二步:给RestTemplate装上这个ErrorHandler

如果是用配置类创建RestTemplate的:

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.client.RestTemplate;

@Configuration
public class RestTemplateConfig {
    @Bean
    public RestTemplate restTemplate() {
        RestTemplate restTemplate = new RestTemplate();
        restTemplate.setErrorHandler(new NoThrowErrorHandler());
        return restTemplate;
    }
}

如果是直接new RestTemplate实例的:

RestTemplate restTemplate = new RestTemplate();
restTemplate.setErrorHandler(new NoThrowErrorHandler());

搞定之后,再调用postForEntity,哪怕对方返回500,也会正常返回包含错误内容、状态码的ResponseEntity,你就可以像处理正常响应一样,用responseEntity.getStatusCode()判断状态,再拿getBody()取错误json了。

3. 用exchange方法(更灵活的可选方案)

其实postForEntity底层也是调用exchange,如果你需要自定义请求头、请求方法这些更灵活的配置,也可以用exchange配合上面的自定义ErrorHandler,效果完全一样:

// 先组装请求实体
HttpHeaders requestHeaders = new HttpHeaders();
requestHeaders.setContentType(MediaType.APPLICATION_JSON);
HttpEntity<String> requestEntity = new HttpEntity<>("你的请求体内容", requestHeaders);

// 调用接口
ResponseEntity<String> responseEntity = restTemplate.exchange(
        url,
        HttpMethod.POST,
        requestEntity,
        String.class
);

// 直接判断状态码处理
if (responseEntity.getStatusCode().is2xxSuccessful()) {
    // 正常逻辑
} else {
    String errorJson = responseEntity.getBody();
    // 处理错误
}
小提醒
  • 用自定义ErrorHandler的时候,记得加日志记录错误情况,不然出问题了连排查线索都没有。
  • 捕获异常的方式适合只在个别调用点处理错误的场景,自定义ErrorHandler更适合全局统一处理的场景。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.25 07:46:29