问题描述
在RestTemplate请求Api时,返回的Response状态码不为200时,RestTemplate会抛出异常,导致我们获取不到Response。原因是RestTemplate中定义了默认异常处理类,在状态码不为200时抛出异常。这并不符合我们的期望,我们希望直接拿到响应体,并且根据我们的业务需要,不同的状态码抛出不同的业务异常。
以下为RestTemplate源码,我们发现他的默认异常处理类只抛出三类异常。
public class DefaultResponseErrorHandler implements ResponseErrorHandler {
/**
* Delegates to {@link #hasError(HttpStatus)} (for a standard status enum value) or
* {@link #hasError(int)} (for an unknown status code) with the response status code.
* @see ClientHttpResponse#getRawStatusCode()
* @see #hasError(HttpStatus)
* @see #hasError(int)
*/
@Override
public boolean hasError(ClientHttpResponse response) throws IOException {
int rawStatusCode = response.getRawStatusCode();
HttpStatus statusCode = HttpStatus.resolve(rawStatusCode);
return (statusCode != null ? hasError(statusCode) : hasError(rawStatusCode));
}
......
/**
* Handle the error based on the resolved status code.
*
* <p>The default implementation delegates to
* {@link HttpClientErrorException#create} for errors in the 4xx range, to
* {@link HttpServerErrorException#create} for errors in the 5xx range,
* or otherwise raises {@link UnknownHttpStatusCodeException}.
*
* @since 5.0
* @see HttpClientErrorException#create
* @see HttpServerErrorException#create
*/
protected void handleError(ClientHttpResponse response, HttpStatus statusCode) throws IOException {
String statusText = response.getStatusText();
HttpHeaders headers = response.getHeaders();
byte[] body = getResponseBody(response);
Charset charset = getCharset(response);
String message = getErrorMessage(statusCode.value(), statusText, body, charset);
switch (statusCode.series()) {
case CLIENT_ERROR:
throw HttpClientErrorException.create(message, statusCode, statusText, headers, body, charset);
case SERVER_ERROR:
throw HttpServerErrorException.create(message, statusCode, statusText, headers, body, charset);
default:
throw new UnknownHttpStatusCodeException(message, statusCode.value(), statusText, headers, body, charset);
}
}
......
}
解决方案
这时候我们需要使用RestTemplate中的自定义异常处理类,使得任何状态码都不会抛出异常,这样我们就可以在自己的系统中根据Response的状态码处理异常。
自定义异常处理类
/**
* 忽略异常处理器
* 该异常处理器会忽略RestTemplate中的异常状态码
*/
public static class IgnoreErrorHandler implements ResponseErrorHandler {
/**
* 忽略所有异常
*
* @param response the response to inspect
* @return false
*/
@Override
public boolean hasError(@NotNull ClientHttpResponse response) {
return false;
}
@Override
public void handleError(@NotNull ClientHttpResponse response) {
}
}
自定义异常处理类注册
// 创建RestTemplate实例
RestTemplate restTemplate = new RestTemplate();
// 设置自定义异常处理
restTemplate.setErrorHandler(new IgnoreErrorHandler());
设置了自定义异常处理器之后,我们就可以根据状态码来进行异常处理了。