关注wx:CodingTechWork
引言
在代码开发过程中,发现很多地方通过RestTemplate
调用了第三方接口,而第三方接口需要根据某些状态码或者异常进行重试调用,此时,要么在每个调用的地方进行异常捕获,然后重试;要么在封装的RestTemplate
工具类中进行统一异常捕获和封装。当然,本文不走寻常路,将会通过RestTemplate
的异常处理器进行操作。
RestTemplate异常处理器介绍
分类
异常处理器 | 功能描述 |
---|---|
ResponseErrorHandler | 异常处理器接口,是restTemplate所有异常处理器的实现接口 |
DefaultResponseErrorHandler | 默认的异常处理器,处理客户端和服务端异常 |
ExtractingResponseErrorHandler | 将HTTP错误响应转换RestClientException |
NoOpResponseErrorHandler | 不处理异常 |
RestTemplate异常处理器源码
ResponseErrorHandler
public interface ResponseErrorHandler {
/**
* 判断请求是否异常
* false: 请求返回无错误
* true: 请求返回有错误
* 可定制化根据某一些status的值进行返回,如根据2xx返回false,非2xx返回true
* 同时,可根据ClientHttpResponse的返回结果来定制化判断
*/
boolean hasError(ClientHttpResponse var1) throws IOException;
/**
* 处理错误
*/
void handleError(ClientHttpResponse var1) throws IOException;
/**
* 默认的异常处理方法
*/
default void handleError(URI url, HttpMethod method, ClientHttpResponse response) throws IOException {
//默认调用handleError(response)方法,也可以重写该方法
this.handleError(response);
}
}
DefaultResponseErrorHandler
package org.springframework.web.client;
import java.io.IOException;
import java.nio.charset.Charset;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.HttpStatus.Series;
import org.springframework.http.client.ClientHttpResponse;
import org.springframework.lang.Nullable;
import org.springframework.util.FileCopyUtils;
public class DefaultResponseErrorHandler implements ResponseErrorHandler {
public DefaultResponseErrorHandler() {
}
/**
* 判断请求是否异常
*/
public boolean hasError(ClientHttpResponse response) throws IOException {
HttpStatus statusCode = HttpStatus.resolve(response.getRawStatusCode());
//statusCode不为空并调用受保护的方法hasError()方法
return statusCode != null && this.hasError(statusCode);
}
protected boolean hasError(HttpStatus statusCode) {
//遇到客户端错误4xx或服务端错误5xx,就返回true表示有错误
return statusCode.series() == Series.CLIENT_ERROR || statusCode.series() == Series.SERVER_ERROR;
}
/**
* 处理错误
*/
public void handleError(ClientHttpResponse response) throws IOException {
//获取状态码
HttpStatus statusCode = HttpStatus.resolve(response.getRawStatusCode());
if (statusCode == null) {
throw new UnknownHttpStatusCodeException(response.getRawStatusCode(), response.getStatusText(), response.getHeaders(), this.getResponseBody(response), this.getCharset(response));
} else {
//状态码不为空,则处理错误(主要是4xx和5xx错误)
this.handleError(response, statusCode);
}
}
/**
* 处理错误
*/
protected void handleError(ClientHttpResponse response, HttpStatus statusCode) throws IOException {
String statusText = response.getStatusText();
HttpHeaders headers = response.getHeaders();
byte[] body = this.getResponseBody(response);
Charset charset = this.getCharset(response);
switch(statusCode.series()) {
case CLIENT_ERROR:
//http客户端错误
throw HttpClientErrorException.create(statusCode, statusText, headers, body, charset);
case SERVER_ERROR:
//http服务端错误
throw HttpServerErrorException.create(statusCode, statusText, headers, body, charset);
default:
throw new UnknownHttpStatusCodeException(statusCode.value(), statusText, headers, body, charset);
}
}
/** @deprecated */
@Deprecated
protected HttpStatus getHttpStatusCode(ClientHttpResponse response) throws IOException {
HttpStatus statusCode = HttpStatus.resolve(response.getRawStatusCode());
if (statusCode == null) {
throw new UnknownHttpStatusCodeException(response.getRawStatusCode(), response.getStatusText(), response.getHeaders(), this.getResponseBody(response), this.getCharset(response));
} else {
return statusCode;
}
}
protected byte[] getResponseBody(ClientHttpResponse response) {
try {
return FileCopyUtils.copyToByteArray(response.getBody());
} catch (IOException var3) {
return new byte[0];
}
}
@Nullable
protected Charset getCharset(ClientHttpResponse response) {
HttpHeaders headers = response.getHeaders();
MediaType contentType = headers.getContentType();
return contentType != null ? contentType.getCharset() : null;
}
}
ExtractingResponseErrorHandler
package org.springframework.web.client;
import java.io.IOException;
import java.util.Collections;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import org.springframework.http.HttpStatus;
import org.springframework.http.HttpStatus.Series;
import org.springframework.http.client.ClientHttpResponse;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.lang.Nullable;
import org.springframework.util.CollectionUtils;
public class ExtractingResponseErrorHandler extends DefaultResponseErrorHandler {
//定义HttpMessageConverter对象列表
private List