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

Spring REST中RestClientResponseException缺失响应体的解决方法

解决RestTemplate调用时无法获取自定义ErrorObject响应体的问题

这个问题我之前也碰到过,核心原因是RestClientResponseException虽然包含了响应体,但默认不会自动帮你反序列化为ErrorObject,需要我们手动处理或者配置RestTemplate的错误处理器来实现。下面给你两种可行的方案:

方案一:手动从异常中提取响应体并反序列化

RestClientResponseException提供了getResponseBodyAsString()方法,可以直接拿到响应体的JSON字符串,然后用Jackson的ObjectMapper手动转成ErrorObject。代码示例如下:

try {
    ResponseEntity<WhateverObject> entity = restTemplate.exchange(url, HttpMethod.POST, getBaseHeadersAsHttpEntity(), WhateverObject.class);
    // 正常业务逻辑
} catch (RestClientResponseException e) {
    ObjectMapper objectMapper = new ObjectMapper();
    try {
        // 把响应体字符串反序列化为ErrorObject
        ErrorObject errorObject = objectMapper.readValue(e.getResponseBodyAsString(), ErrorObject.class);
        // 这里就可以使用errorObject里的name、status、message了
        System.out.println("错误信息:" + errorObject.getMessage());
    } catch (JsonProcessingException ex) {
        // 处理反序列化失败的情况,比如响应体不是预期的JSON格式
        ex.printStackTrace();
    }
}

这种方法简单直接,不需要修改RestTemplate的配置,适合快速解决问题。

方案二:自定义RestTemplate的错误处理器

如果希望每次调用都自动解析错误响应体,不用每次都手动反序列化,可以自定义ResponseErrorHandler,让RestTemplate在抛出异常时直接携带解析好的ErrorObject。

步骤1:创建自定义异常类

用来包装错误状态码和ErrorObject:

public class CustomRestClientException extends RuntimeException {
    private HttpStatus statusCode;
    private ErrorObject errorObject;

    public CustomRestClientException(HttpStatus statusCode, ErrorObject errorObject) {
        super(errorObject.getMessage());
        this.statusCode = statusCode;
        this.errorObject = errorObject;
    }

    // 生成getter方法
    public HttpStatus getStatusCode() {
        return statusCode;
    }

    public ErrorObject getErrorObject() {
        return errorObject;
    }
}

步骤2:实现自定义ResponseErrorHandler

继承默认的DefaultResponseErrorHandler,重写错误处理逻辑:

import org.springframework.http.client.ClientHttpResponse;
import org.springframework.web.client.DefaultResponseErrorHandler;
import com.fasterxml.jackson.databind.ObjectMapper;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import org.springframework.util.StreamUtils;
import org.springframework.http.HttpStatus;

public class CustomResponseErrorHandler extends DefaultResponseErrorHandler {
    private final ObjectMapper objectMapper = new ObjectMapper();

    @Override
    public void handleError(ClientHttpResponse response) throws IOException {
        HttpStatus statusCode = HttpStatus.resolve(response.getRawStatusCode());
        if (statusCode != null && hasError(statusCode)) {
            // 读取响应体字符串
            String responseBody = StreamUtils.copyToString(response.getBody(), StandardCharsets.UTF_8);
            // 反序列化为ErrorObject
            ErrorObject errorObject = objectMapper.readValue(responseBody, ErrorObject.class);
            // 抛出自定义异常,携带解析后的ErrorObject
            throw new CustomRestClientException(statusCode, errorObject);
        }
        // 其他情况交给父类处理
        super.handleError(response);
    }
}

步骤3:配置RestTemplate使用自定义错误处理器

在创建RestTemplate的时候设置我们的错误处理器:

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

之后调用接口时,直接捕获CustomRestClientException就能拿到解析好的ErrorObject了:

try {
    ResponseEntity<WhateverObject> entity = restTemplate.exchange(url, HttpMethod.POST, getBaseHeadersAsHttpEntity(), WhateverObject.class);
    // 正常业务逻辑
} catch (CustomRestClientException e) {
    ErrorObject errorObject = e.getErrorObject();
    System.out.println("错误名称:" + errorObject.getName());
    System.out.println("状态码:" + errorObject.getStatus());
    System.out.println("错误消息:" + errorObject.getMessage());
}

注意事项

  • 确保你的ErrorObject类有正确的getter/setter方法,或者使用@Data注解(Lombok),否则Jackson无法正常反序列化。
  • 确认服务器返回的响应头Content-Type是application/json,并且RestTemplate的消息转换器中包含MappingJackson2HttpMessageConverter(Spring Boot默认会配置)。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.27 09:59:28