问题描述
我正在使用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
}
}
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());