【发布时间】:2018-03-26 06:10:00
【问题描述】:
我正在尝试记录每个请求的请求-响应对。问题是当响应代码为401 时,ClientHttpResponse.getBody() 会抛出 ResourceAccessException 并且我无法读取响应正文。
这是 RestTemplate 配置
RestTemplate restTemplate = new RestTemplate();
// Added this requestFactory to make response object readable more than once.
ClientHttpRequestFactory requestFactory =
new BufferingClientHttpRequestFactory(new SimpleClientHttpRequestFactory());
restTemplate.setRequestFactory(requestFactory);
restTemplate.getInterceptors().add(new RequestLoggingInterceptor(vCloudRequest.getAction(),httpHeaders));
restTemplate.setErrorHandler(new RequestErrorHandler());
return restTemplate;
下面拦截器的最后一行抛出如下异常。
我该如何解决这个问题?
org.springframework.web.client.ResourceAccessException: I/O 错误 “https://example.com/api/sessions”的 POST 请求:服务器返回 HTTP 响应代码:401 用于 URL:https://example.com/api/sessions; 嵌套异常是 java.io.IOException:服务器返回 HTTP 响应 代码:401 用于 URL:https://example.com.11/api/sessions
这是拦截器的相关部分。
@Override
public ClientHttpResponse intercept(HttpRequest request, byte[] body, ClientHttpRequestExecution execution) throws IOException {
ClientHttpResponse response = execution.execute(request, body);
String requestString = new String(body);
// Calling this method because when we make a POST or PUT request and get an error
// response.getBody() throws IOException. But if we call response.getStatusCode() it works fine.
// I don't know the reason.
// I asked a question on stackoverflow
// https://stackoverflow.com/questions/47429978/resttemplate-response-getbody-throws-exception-on-4-and-5-errors-for-put-and
response.getStatusCode();
String responseString = new String(ByteStreams.toByteArray(response.getBody()), Charset.forName("UTF-8"));
...
}
这是自定义错误处理程序
公共类 RequestErrorHandler 实现 ResponseErrorHandler {
@Override
public boolean hasError(ClientHttpResponse response) throws IOException {
if (!response.getStatusCode().is2xxSuccessful()) {
return true;
}
return false;
}
@Override
public void handleError(ClientHttpResponse response) throws IOException {
JAXBElement<ErrorType> root = null;
try {
JAXBContext jaxbContext = JAXBContext.newInstance(ErrorType.class);
Unmarshaller jaxbUnmarshaller = jaxbContext.createUnmarshaller();
root = jaxbUnmarshaller.unmarshal(new StreamSource(
response.getBody()), ErrorType.class);
} catch (JAXBException e) {
throw new IOException("XML converting error. Cannot convert response to ErrorType");
}
ErrorType error = root.getValue();
throw new VcloudException(error);
}
}
【问题讨论】:
-
您期望
401的响应正文是什么? -
其实服务器是否发送响应体并不重要。 ,如果它没有发送任何响应正文,我想将 responseString 设置为空。但它会引发异常。
-
你看到这个答案stackoverflow.com/a/47467572/4545442了吗?可能会有帮助..
-
在您的错误消息
Server returned HTTP response code: 401 for URL: https://example.com.11/api/sessions中。此 URL 只是一个拼写错误还是实际上更改了要请求的 URL? -
另外,@SalihErikci 你确定异常是由
response.getBody()而不是ByteStreams.toByteArray(..)引发的吗?因为如果抛出 I/O 异常,rest 模板倾向于用ResourceAccessException包装它
标签: java spring resttemplate