当前位置: 代码迷 >> java >> 从Spring RestTemplate出来的IOException未被自定义ResponseErrorHandler接收
  详细解决方案

从Spring RestTemplate出来的IOException未被自定义ResponseErrorHandler接收

热度:45   发布时间:2023-07-31 11:09:45.0

我正在使用Spring's RestTemplate对第三方服务进行一些API调用。

当响应以200 SUCCESS返回时,一切都按预期工作。

但是,当响应是一个400-level error ,我从RestTemplate代码的深处得到了IOException

这令人沮丧,因为我实际上已经编写了自己的ResponseErrorHandler实现,该实现可以检查某些非200错误并执行我选择的操作(记录,重新格式化等)。

在其他所有第三方API上,我的ResponseErrorHandler实现都可以使用,但是特别是对于此服务器,所有非200错误都会导致此IOException ,并且永远无法达到我的自定义实现。

注意:当我尝试点击此第三方端点时,Curl似乎通常会返回错误。

这是Spring错误吗? 我在做蠢事吗? 有关如何解决的想法?

相关代码

堆栈跟踪异常:

Caused by: org.springframework.web.client.ResourceAccessException: I/O error on POST request for "https://third-party.com/api/v2/some-resource": Server returned HTTP response code: 400 for URL: https://third-party.com/api/v2/some-resource; nested exception is java.io.IOException: Server returned HTTP response code: 400 for URL: https://third-party.com/api/v2/some-resource
at org.springframework.web.client.RestTemplate.doExecute(RestTemplate.java:743) ~[spring-web-5.1.3.RELEASE.jar:5.1.3.RELEASE]
at org.springframework.web.client.RestTemplate.execute(RestTemplate.java:669) ~[spring-web-5.1.3.RELEASE.jar:5.1.3.RELEASE]
at org.springframework.web.client.RestTemplate.exchange(RestTemplate.java:607) ~[spring-web-5.1.3.RELEASE.jar:5.1.3.RELEASE]
at org.myowncode.commons.client.RestClient.send(RestClient.java:74) ~[classes/:na]

我的自定义ResponseErrorHandler的用法

this.restTemplate = new RestTemplate(new BufferingClientHttpRequestFactory(new SimpleClientHttpRequestFactory()));
restTemplate.setErrorHandler(new LoggingResponseErrorHandler());

我的自定义ResponseErrorHandler的示例

(这应该是无关紧要的,因为无论我是否已注册,上述情况都会发生)

public class LoggingResponseErrorHandler implements ResponseErrorHandler {

    private static final Logger logger = LoggerFactory.getLogger(LoggingResponseErrorHandler.class);

    @Override
    public boolean hasError(ClientHttpResponse response) throws IOException {
        // do my own thing
    }

    @Override
    public void handleError(ClientHttpResponse response) throws IOException {
        // do my own thing
    }

}

我怀疑这与BufferingClientHttpRequestFactory的使用有关。 一个SimpleBufferingClientHttpRequest似乎可以让IOException逃脱其executeInternal()方法,而非缓冲版本SimpleStreamingClientHttpRequest可以捕获并忽略它,这大概会让您处理响应。

    @Override
protected ClientHttpResponse executeInternal(HttpHeaders headers) throws IOException {
    try {
        if (this.body != null) {
            this.body.close();
        }
        else {
            SimpleBufferingClientHttpRequest.addHeaders(this.connection, headers);
            this.connection.connect();
            // Immediately trigger the request in a no-output scenario as well
            this.connection.getResponseCode();
        }
    }
    catch (IOException ex) {
        // ignore
    }
    return new SimpleClientHttpResponse(this.connection);
}

尝试像这样创建restTemplate:

this.restTemplate = new RestTemplate(new SimpleClientHttpRequestFactory());
  相关解决方案