有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

来自Spring RestTemplate的java IOException未被自定义ResponseErrorHandler拾取

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

当响应以200 SUCCESS的形式返回时,一切都按预期进行

然而,当响应是400-level error时,我从RestTemplate代码的腹部深处得到一个IOException

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

在其他每一个第三方API上,我的ResponseErrorHandler实现都有效,但对于这个服务器,所有非200错误都会导致这个IOException,并且我的自定义实现永远无法实现

Note: Curl seems to return the error normally when I try hitting this third-party endpoint.

这是一个春天的虫子吗?我在做傻事吗?如何解决问题的想法

相关代码

异常的堆栈跟踪:

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
    }

}

共 (1) 个答案

  1. # 1 楼答案

    我怀疑这与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());