在我们使用Spring框架进行应用开发的时候,RestTemplate组件的使用越来越频繁,在这里我简单的梳理下它的源码,从而更深入的理解其工作原理,同时也为后面的Ribbon的使用打下基础。
首先我们从一张较为简洁的类图开始,从全局了解其继承关系
1,HttpAccessor抽象类
在该抽象类中重点关注setRequestFactory、getRequestFactory与createRequest三个方法。顾名思义,setRequestFactory与getRequestFactory分别就是为了设置属性requestFactory的值以及返回该值,createRequest方法是根据请求的URI地址以及请求的HTTP方法得到一个ClientHttpRequest类型的对象。
默认其requestFactory属性为ClientHttpRequestFactory类型的SimpleClientHttpRequestFactory实例对象。该实例的内部将使用JDK自带的HttpURLConnection来建立http连接,如下所示
@Override
public ClientHttpRequest createRequest(URI uri, HttpMethod httpMethod) throws IOException {
HttpURLConnection connection = openConnection(uri.toURL(), this.proxy);
prepareConnection(connection, httpMethod.name());
if (this.bufferRequestBody) {
return new SimpleBufferingClientHttpRequest(connection, this.outputStreaming);
} else {
return new SimpleStreamingClientHttpRequest(connection, this.chunkSize, this.outputStreaming);
}
}
重点:RequestFactory必须是ClientHttpRequestFactory类型的。 除了这里默认的SimpleClientHttpRequestFactory,常用的还有InterceptingClientHttpRequestFactory。
2,InterceptingHttpAccessor抽象类
该类重写了HttpAccessor中的getRequestFactory方法,如果其中的拦截器(interceptors)为空,则直接调用父类的getRequestFactory方法直接返回,否则实例化InterceptingClientHttpRequestFactory工厂对象并返回,如下代码所示
@Override
public ClientHttpRequestFactory getRequestFactory() {
List<ClientHttpRequestInterceptor> interceptors = getInterceptors();
if (!CollectionUtils.isEmpty(interceptors)) {
ClientHttpRequestFactory factory = this.interceptingRequestFactory;
if (factory == null) {
factory = new InterceptingClientHttpRequestFactory(super.getRequestFactory(), interceptors);
this.interceptingRequestFactory = factory;
}
return factory;
} else {
return super.getRequestFactory();
}
}
其InterceptingClientHttpRequestFactory的createRequest方法将返回一个ClientHttpRequest类型的InterceptingClientHttpRequest实例对象
而默认的SimpleClientHttpRequestFactory返回的是ClientHttpRequest类型的SimpleBufferingClientHttpRequest或者SimpleStreamingClientHttpRequest
@Override
public final ClientHttpRequest createRequest(URI uri, HttpMethod httpMethod) throws IOException {
return createRequest(uri, httpMethod, this.requestFactory);
}
@Override
protected ClientHttpRequest createRequest(URI uri, HttpMethod httpMethod, ClientHttpRequestFactory requestFactory) {
return new InterceptingClientHttpRequest(requestFactory, this.interceptors, uri, httpMethod);
}
重点:使用不同的RequestFactory返回具有不同功能的ClientHttpRequest 类型的实例对象,然后通过调用其 execute() 方法来得到ClientHttpResponse响应对象。
在返回ClientHttpResponse类型对象的过程中具体要做些什么事情完全由ClientHttpRequest的实现类自我决定。
3,RestOperations接口
该接口主要是定义了一些访问方法,例如getForObject、getForEntity等,简要列举如下:
public interface RestOperations {
<T> T getForObject(String url, Class<T> responseType, Map<String, ?> uriVariables) throws RestClientException;
HttpHeaders headForHeaders(String url, Map<String, ?> uriVariables) throws RestClientException;
<T> T postForObject(String url, @Nullable Object request, Class<T> responseType,
Map<String, ?> uriVariables) throws RestClientException;
<T> ResponseEntity<T> exchange(RequestEntity<?> requestEntity, Class<T> responseType) throws RestClientException;
<T> T execute(String url, HttpMethod method, @Nullable RequestCallback requestCallback,@Nullable ResponseExtractor<T> responseExtractor, Map<String, ?> uriVariables) throws RestClientException;
}
4,RestTemplate类
在RestTemplate的构造方法中会初始化许多消息转换器(HttpMessageConverter),以及用于解析URL模板(字符串)的UriTemplateHandler类型对象(DefaultUriBuilderFactory),其它的都是对父级接口的实现。
接下来我们根据一个方法调用来跟踪其执行流程
从上可知,RestTemplate的实现原理其实还挺简单的,很多时候其默认的配置就已经够我们使用了,那么哪些地方可能是我们可以进行扩展时需要考虑的地方呢,或者我们要对其功能进行扩展时应该从哪里入手呢?
RestTemplate中进行扩展最重要的地方就是ClientHttpRequestFactory与ClientHttpRequestInterceptor了。通过自定义ClientHttpRequestFactory我们可以使用apache Http Client或者okHttp组件来发起http的请求操作,同时返回我们自定义的ClientHttpRequest及ClientHttpResponse对象; 而通过自定义的ClientHttpRequestInterceptor对象,我们可以在发起请求的时候对请求进行拦截,对请求的参数等进行修改等。
下面我们从一个请求发起开始来分析整个流程,假定我们调用RestTemplate的getForObject方法
//调用RestTemplate的该方法发起请求
public <T> T getForObject(String url, Class<T> responseType, Object... uriVariables) throws RestClientException {
RequestCallback requestCallback = acceptHeaderRequestCallback(responseType);
HttpMessageConverterExtractor<T> responseExtractor = new HttpMessageConverterExtractor<>(responseType, getMessageConverters(), logger);
return execute(url, HttpMethod.GET, requestCallback, responseExtractor, uriVariables);
}
public <T> T execute(String url, HttpMethod method, @Nullable RequestCallback requestCallback,@Nullable ResponseExtractor<T> responseExtractor, Object... uriVariables) throws RestClientException {
//对URL模板字符串进行解析
URI expanded = getUriTemplateHandler().expand(url, uriVariables);
//执行请求【参照下面的方法】
return doExecute(expanded, method, requestCallback, responseExtractor);
}
protected <T> T doExecute(URI url, @Nullable HttpMethod method, @Nullable RequestCallback requestCallback,@Nullable ResponseExtractor<T> responseExtractor) throws RestClientException {
Assert.notNull(url, "URI is required");
Assert.notNull(method, "HttpMethod is required");
ClientHttpResponse response = null;
try {
//针对要访问的URL和使用的HTTP方法创建请求对象【参照下面的方法】
ClientHttpRequest request = createRequest(url, method);
if (requestCallback != null) {
requestCallback.doWithRequest(request);
}
//执行请求得到响应结果
response = request.execute();
//对响应结果进行处理
handleResponse(url, method, response);
return (responseExtractor != null ? responseExtractor.extractData(response) : null);
} catch (IOException ex) {
String resource = url.toString();
String query = url.getRawQuery();
resource = (query != null ? resource.substring(0, resource.indexOf('?')) : resource);
throw new ResourceAccessException("I/O error on " + method.name() +" request for \"" + resource + "\": " + ex.getMessage(), ex);
} finally {
if (response != null) {
response.close();
}
}
}
protected ClientHttpRequest createRequest(URI url, HttpMethod method) throws IOException {
//获取请求对象工厂并创建请求对象【参照下面的方法】
ClientHttpRequest request = getRequestFactory().createRequest(url, method);
initialize(request);
if (logger.isDebugEnabled()) {
logger.debug("HTTP " + method.name() + " " + url);
}
return request;
}
//重写父类方法,根据是否设置拦截器来返回合适的工厂对象
public ClientHttpRequestFactory getRequestFactory() {
List<ClientHttpRequestInterceptor> interceptors = getInterceptors();
if (!CollectionUtils.isEmpty(interceptors)) {
//如果有设置拦截器,则使用InterceptingClientHttpRequestFactory工厂对象
ClientHttpRequestFactory factory = this.interceptingRequestFactory;
if (factory == null) {
factory = new InterceptingClientHttpRequestFactory(super.getRequestFactory(), interceptors);
this.interceptingRequestFactory = factory;
}
return factory;
} else {
return super.getRequestFactory();
}
}
InterceptingClientHttpRequestFactory类的实现如下
public class InterceptingClientHttpRequestFactory extends AbstractClientHttpRequestFactoryWrapper {
//所有的拦截器对象
private final List<ClientHttpRequestInterceptor> interceptors;
public InterceptingClientHttpRequestFactory(ClientHttpRequestFactory requestFactory,@Nullable List<ClientHttpRequestInterceptor> interceptors) {
super(requestFactory);
this.interceptors = (interceptors != null ? interceptors : Collections.emptyList());
}
//重写父类的方法返回针对具有拦截器情况的InterceptingClientHttpRequest对象
@Override
protected ClientHttpRequest createRequest(URI uri, HttpMethod httpMethod, ClientHttpRequestFactory requestFactory) {
return new InterceptingClientHttpRequest(requestFactory, this.interceptors, uri, httpMethod);
}
}
InterceptingClientHttpRequest类的实现如下
class InterceptingClientHttpRequest extends AbstractBufferingClientHttpRequest {
private final ClientHttpRequestFactory requestFactory;
private final List<ClientHttpRequestInterceptor> interceptors;
private HttpMethod method;
private URI uri;
protected InterceptingClientHttpRequest(ClientHttpRequestFactory requestFactory,List<ClientHttpRequestInterceptor> interceptors, URI uri, HttpMethod method) {
this.requestFactory = requestFactory;
this.interceptors = interceptors;
this.method = method;
this.uri = uri;
}
@Override
public HttpMethod getMethod() {
return this.method;
}
@Override
public String getMethodValue() {
return this.method.name();
}
@Override
public URI getURI() {
return this.uri;
}
@Override
protected final ClientHttpResponse executeInternal(HttpHeaders headers, byte[] bufferedOutput) throws IOException {
InterceptingRequestExecution requestExecution = new InterceptingRequestExecution();
return requestExecution.execute(this, bufferedOutput);
}
//创建一个ClientHttpRequestExecution类型的内部类来执行所有拦截器并发起请求
private class InterceptingRequestExecution implements ClientHttpRequestExecution {
private final Iterator<ClientHttpRequestInterceptor> iterator;
public InterceptingRequestExecution() {
this.iterator = interceptors.iterator();
}
//该方法在拦截器中也会被调用,从而实现迭代执行所有拦截器的效果
@Override
public ClientHttpResponse execute(HttpRequest request, byte[] body) throws IOException {
if (this.iterator.hasNext()) {
ClientHttpRequestInterceptor nextInterceptor = this.iterator.next();
return nextInterceptor.intercept(request, body, this);
} else {
//当所有拦截器都执行完成后便开始发起HTTP请求
HttpMethod method = request.getMethod();
Assert.state(method != null, "No standard HTTP method");
//通过设置的requestFactory来创建ClientHttpRequest类型的对象并发起请求
//可以通过改变requestFactory来改变默认的行为
ClientHttpRequest delegate = requestFactory.createRequest(request.getURI(), method);
request.getHeaders().forEach((key, value) -> delegate.getHeaders().addAll(key, value));
if (body.length > 0) {
if (delegate instanceof StreamingHttpOutputMessage) {
StreamingHttpOutputMessage streamingOutputMessage = (StreamingHttpOutputMessage) delegate;
streamingOutputMessage.setBody(outputStream -> StreamUtils.copy(body, outputStream));
} else {
StreamUtils.copy(body, delegate.getBody());
}
}
//执行请求操作
return delegate.execute();
}
}
}
}
在调用execute()方法时会间接的调用executeInternal方法并返回。在该方法里面创建了一个InterceptingRequestExecution对象,InterceptingRequestExecution对象的execute方法在执行的过程中会被迭代的调用(被各个拦截器调用),直到所有的拦截器都执行完后才开始创建要执行HTTP请求的ClientHttpRequest对象,然后执行并返回结果。
我们找一个BasicAuthorizationInterceptor拦截器看其内部实现
public class BasicAuthorizationInterceptor implements ClientHttpRequestInterceptor {
private final String username;
private final String password;
public BasicAuthorizationInterceptor(@Nullable String username, @Nullable String password) {
Assert.doesNotContain(username, ":", "Username must not contain a colon");
this.username = (username != null ? username : "");
this.password = (password != null ? password : "");
}
@Override
public ClientHttpResponse intercept(HttpRequest request, byte[] body, ClientHttpRequestExecution execution) throws IOException {
//加上需要的请求头数据
String token = Base64Utils.encodeToString((this.username + ":" + this.password).getBytes(StandardCharsets.UTF_8));
request.getHeaders().add("Authorization", "Basic " + token);
//继续执行后面的拦截器对象
return execution.execute(request, body);
}
}
重点:可见,RestTemplate在执行调用的时候主要就是经过了以下三步
- 使用ClientHttpRequestFactory类型对象创建ClientHttpRequest类型对象【例如可以执行拦截器的 InterceptingClientHttpRequest 】
- 执行ClientHttpRequest类型实例对象的execute()方法得到ClientHttpResponse类型的响应结果
- 对响应结果进行处理并返回给调用者
小结
通过以上的分析,应该已经可以很好的理解RestTemplate的执行原理了,我们也可以通过自定义RequestFactory和拦截器的方式来扩展其功能,例如使用RestTemplate完成客户端负载均衡等。最后提供一张较为完整的类图,供大家参考