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

Spring RestClient遇IOException/ResourceAccessException时如何读取响应体?

问题:使用RestClient发送请求时无法读取400错误的响应体

我用RestClient(不是RestTemplate)调用其他服务器接口,因缺少请求头返回400错误,但程序里读不到响应体。用Postman请求能拿到内容为"header XY missing"的响应,现在需要在程序中获取该错误信息,找到读取/记录响应体的方法。


现有代码实现

1. 请求方法代码

public boolean myMethod(String body, String baseUrl, String token) {
    return restClient.post()
            .uri(baseUrl + "/myEndpoint")
            .headers(
                    httpHeaders -> {
                        httpHeaders.set("Calling-Application", "IGPR");
                        httpHeaders.set("Content-Type", "application/json");
                        httpHeaders.set("Locale", "deu-DEU");
                        httpHeaders.set("Authorization", "Bearer " + token);
                    })
            .body(body)
            .exchange((req, res) -> {
                try {
                    if (res.getStatusCode().is2xxSuccessful()) {
                        return true;
                    }
                } catch (HttpClientErrorException e) {
                    e.printStackTrace();
                } catch (IOException re) {    // 这里不生效!
                    System.out.println(res.getBody());
                }
                return false;
            });
}

2. 日志拦截器代码

public class RequestResponseLoggingInterceptor implements ClientHttpRequestInterceptor {

private final Logger log = LoggerFactory.getLogger(this.getClass());

@Override
public ClientHttpResponse intercept(HttpRequest request, byte[] body, ClientHttpRequestExecution execution) throws IOException {
    logRequest(request, body);
    ClientHttpResponse response = execution.execute(request, body);
    BufferedClientHttpResponseWrapper responseWrapper = new BufferedClientHttpResponseWrapper(response);
    logResponse(responseWrapper);
    return responseWrapper;
}

private void logRequest(HttpRequest request, byte[] body) throws IOException {
    log.debug("===========================request begin================================================");
    log.debug("URI         : {}", request.getURI());
    log.debug("Method      : {}", request.getMethod());
    log.debug("Headers     : {}", request.getHeaders());
    log.debug("Request body: {}", new String(body, StandardCharsets.UTF_8));
    log.debug("==========================request end================================================");
}

private void logResponse(ClientHttpResponse response) throws IOException {
    log.debug("============================response begin==========================================");
    log.debug("Status code  : {}", response.getStatusCode());
    log.debug("Status text  : {}", response.getStatusText());
    log.debug("Headers      : {}", response.getHeaders());
    log.debug("Response body: {}", StreamUtils.copyToString(response.getBody(), Charset.defaultCharset()));
    log.debug("=======================response end=================================================");
}
}

3. 响应包装类代码

public class BufferedClientHttpResponseWrapper implements ClientHttpResponse {

private final ClientHttpResponse response;
private byte[] body;

public BufferedClientHttpResponseWrapper(ClientHttpResponse response) throws IOException {
    this.response = response;
    this.body = StreamUtils.copyToByteArray(response.getBody());
}

@Override
public InputStream getBody() throws IOException {
    return new ByteArrayInputStream(body);
}


@Override
public String getStatusText() throws IOException {
    return response.getStatusText();
}

@Override
public void close() {
    response.close();
}

@Override
public org.springframework.http.HttpHeaders getHeaders() {
    return response.getHeaders();
}

@Override
public HttpStatusCode getStatusCode() throws IOException {
    return response.getStatusCode();
}
}

解决方案

1. 在exchange回调中直接读取错误响应体

原代码的HttpClientErrorException捕获逻辑不生效,因为RestClient的exchange回调不会自动抛出该异常,需手动读取响应体:

修改后的请求方法:

public boolean myMethod(String body, String baseUrl, String token) {
    return restClient.post()
            .uri(baseUrl + "/myEndpoint")
            .headers(httpHeaders -> {
                httpHeaders.set("Calling-Application", "IGPR");
                httpHeaders.set("Content-Type", "application/json");
                httpHeaders.set("Locale", "deu-DEU");
                httpHeaders.set("Authorization", "Bearer " + token);
            })
            .body(body)
            .exchange((req, res) -> {
                HttpStatusCode statusCode = res.getStatusCode();
                if (statusCode.is2xxSuccessful()) {
                    return true;
                } else {
                    // 读取错误响应体
                    String errorBody = StreamUtils.copyToString(res.getBody(), StandardCharsets.UTF_8);
                    System.err.println("错误响应内容:" + errorBody);
                    // 可根据业务需求抛出自定义异常或做其他处理
                    throw new RuntimeException("请求失败:" + errorBody);
                }
            });
}

2. 修复日志拦截器不生效问题

拦截器未生效大概率是因为没注册到RestClient实例中,创建RestClient时需添加拦截器:

RestClient restClient = RestClient.builder()
        // 可选:设置基础URL
        .baseUrl("your-base-url")
        // 注册日志拦截器
        .interceptors(new RequestResponseLoggingInterceptor())
        .build();

另外,确保日志级别设置为DEBUG,否则log.debug的内容不会输出。可在application.properties中配置:

logging.level.com.your.package.RequestResponseLoggingInterceptor=DEBUG

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.18 00:05:27