进入RestTemplate的execute方法,其调用了自身的doExecute方法,在doExecute方法中通过createRequest方法创建了ClientHttpRequest对象,通过类名称,我们就可以知道这是一个发起http请求的封装类。那么在createRequest方法中RestTemplate做了哪些事情?
@Nullable
public <T> T execute(String url, HttpMethod method, @Nullable RequestCallback requestCallback, @Nullable ResponseExtractor<T> responseExtractor, Object... uriVariables) throws RestClientException {
URI expanded = this.getUriTemplateHandler().expand(url, uriVariables);
return this.doExecute(expanded, method, requestCallback, responseExtractor);
}
@Nullable
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;
Object resource1;
try {
//创建发起http请求的封装对象
ClientHttpRequest ex = this.createRequest(url, method);
if(requestCallback != null) {
requestCallback.doWithRequest(ex);
}
response = ex.execute();
this.handleResponse(url, method, response);
resource1 = responseExtractor != null?responseExtractor.extractData(response):null;
} catch (IOException var12) {
String resource = url.toString();
String query = url.getRawQuery();
resource = query != null?resource.substring(0, resource.indexOf(63)):resource;
throw new ResourceAccessException("I/O error on " + method.name() + " request for \"" + resource + "\": " + var12.getMessage(), var12);
} finally {
if(response != null) {
response.close();
}
}
return resource1;
}
进入createRequest方法,它是RestTemplate顶级父类HttpAccessor中的方法,主要逻辑为获取RequestFactory后,通过url创建ClientHttpRequest,查看getRequestFactory方法,HttpAccessor中getRequestFactory只是直接返回了requestFactory成员变量,RestTemplate的父类InterceptingHttpAccessor重写了getRequestFactory方法,所以调用的实际是InterceptingHttpAccessor的getRequestFactory
protected ClientHttpRequest createRequest(URI url, HttpMethod method) throws IOException {
ClientHttpRequest request = this.getRequestFactory().createRequest(url, method);
this.initialize(request);
if(this.logger.isDebugEnabled()) {
this.logger.debug("HTTP " + method.name() + " " + url);
}
return request;
}
public ClientHttpRequestFactory getRequestFactory() {
return this.requestFactory;
}
进入InterceptingHttpAccessor的getRequestFactory方法中,它会调用自己的getInterceptors方法(返回interceptors 成员变量,即拦截器列表),并添加interceptors到创建的InterceptingClientHttpRequestFactory对象中,拦截器列表默认为空列表,可以通过InterceptingHttpAccessor.setInterceptors方法添加拦截器,那么这个setInterceptors是在哪里调用的呢?
public ClientHttpRequestFactory getRequestFactory() {
List interceptors = this.getInterceptors();
if(!CollectionUtils.isEmpty(interceptors)) {
Object factory = this.interceptingRequestFactory;
if(factory == null) {
factory = new InterceptingClientHttpRequestFactory(super.getRequestFactory(), interceptors);
this.interceptingRequestFactory = (ClientHttpRequestFactory)factory;
}
return (ClientHttpRequestFactory)factory;
} else {
return super.getRequestFactory();
}
}
public List<ClientHttpRequestInterceptor> getInterceptors() {
return this.interceptors;
}
public void setInterceptors(List<ClientHttpRequestInterceptor> interceptors) {
if(this.interceptors != interceptors) {
this.interceptors.clear();
this.interceptors.addAll(interceptors);
AnnotationAwareOrderComparator.sort(this.interceptors);
}
}
在LoadBalancerAutoConfifiguration.LoadBalancerInterceptorConfig配置类中有一个restTemplateCustomizer方法,其调用了setInterceptors方法,并且添加了LoadBalancerInterceptor到restTemplate的拦截器列表中,我们先记住这里向RestTemplate中设置了LoadBalancerInterceptor拦截器。
@Bean
@ConditionalOnMissingBean
public RestTemplateCustomizer restTemplateCustomizer(LoadBalancerInterceptor loadBalancerInterceptor) {
return (restTemplate) -> {
ArrayList list = new ArrayList(restTemplate.getInterceptors());
list.add(loadBalancerInterceptor);
restTemplate.setInterceptors(list);
};
}
回到HttpAccessor的createRequest中,获取了RequestFactory(InterceptingClientHttpRequestFactory)后,调用了InterceptingClientHttpRequestFactory.createRequest方法,创建了InterceptingClientHttpRequest,它设置了interceptors成员变量。
protected ClientHttpRequest createRequest(URI url, HttpMethod method) throws IOException {
ClientHttpRequest request = this.getRequestFactory().createRequest(url, method);
this.initialize(request);
if(this.logger.isDebugEnabled()) {
this.logger.debug("HTTP " + method.name() + " " + url);
}
return request;
}
protected ClientHttpRequest createRequest(URI uri, HttpMethod httpMethod, ClientHttpRequestFactory requestFactory) {
return new InterceptingClientHttpRequest(requestFactory, this.interceptors, uri, httpMethod);
}
回到RestTemplate的doExecute方法中,会调用 ex.execute()方法,即InterceptingClientHttpRequest父类AbstractClientHttpRequest的execute方法,
public final ClientHttpResponse execute() throws IOException {
this.assertNotExecuted();
ClientHttpResponse result = this.executeInternal(this.headers);
this.executed = true;
return result;
}
最终会调用InterceptingClientHttpRequest的executeInternal方法
protected final ClientHttpResponse executeInternal(HttpHeaders headers, byte[] bufferedOutput) throws IOException {
InterceptingClientHttpRequest.InterceptingRequestExecution requestExecution = new InterceptingClientHttpRequest.InterceptingRequestExecution();
return requestExecution.execute(this, bufferedOutput);
}
public InterceptingRequestExecution() {
this.iterator = InterceptingClientHttpRequest.this.interceptors.iterator();
}
public ClientHttpResponse execute(HttpRequest request, byte[] body) throws IOException {
if(this.iterator.hasNext()) {
//这里拿到的就是拦截器列表的迭代器
ClientHttpRequestInterceptor method1 = (ClientHttpRequestInterceptor)this.iterator.next();
return method1.intercept(request, body, this);
} else {
HttpMethod method = request.getMethod();
Assert.state(method != null, "No standard HTTP method");
ClientHttpRequest delegate = InterceptingClientHttpRequest.this.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();
}
}
InterceptingClientHttpRequest.execute的主要逻辑为,如果存在ClientHttpRequestInterceptor 拦截器列表,依次调用拦截器的intercept方法(这里实现依次调用的方式后面分析),在上面的分析中已经提到,向InterceptingClientHttpRequest.this.interceptors中添加了LoadBalancerInterceptor,查看LoadBalancerInterceptor.intercept方法,主要逻辑为,获取请求的uri,通过uri获取请求的服务服务名名称,调用LoadBalancerClient的execute发起请求,获取请求的结果,那么这里的loadBalancer是具体是那个实现类,怎么注入的?
public ClientHttpResponse intercept(HttpRequest request, byte[] body, ClientHttpRequestExecution execution) throws IOException {
URI originalUri = request.getURI();//获得请求的URI
String serviceName = originalUri.getHost();//获得服务名称
Assert.state(serviceName != null, "Request URI does not contain a valid hostname: " + originalUri);
return (ClientHttpResponse)this.loadBalancer.execute(serviceName, this.requestFactory.createRequest(request, body, execution));
}@Bean
public LoadBalancerInterceptor ribbonInterceptor(LoadBalancerClient loadBalancerClient, LoadBalancerRequestFactory requestFactory) {
return new LoadBalancerInterceptor(loadBalancerClient, requestFactory);
}
重新查看LoadBalancerAutoConfiguration.ribbonInterceptor方法,在创建LoadBalancerInterceptor的时候,通过构造函数传入了LoadBalancerClient ,在RibbonAutoConfiguration.loadBalancerClient方法中创建了RibbonLoadBalancerClient对象,所以LoadBalancerInterceptor.intercept最终调用了RibbonLoadBalancerClient的execute方法。
@Bean
@ConditionalOnMissingBean({LoadBalancerClient.class})
public LoadBalancerClient loadBalancerClient() {
return new RibbonLoadBalancerClient(this.springClientFactory());
}
RibbonLoadBalancerClient.execute方法的主要逻辑为,根据serviceId获得一个ILoadBalancer,通过ILoadBalancer选择可用的服务器,ILoadBalancer是通过RibbonClientConfiguration.ribbonLoadBalancer方法创建的,默认为ZoneAwareLoadBalancer类型。
public <T> T execute(String serviceId, LoadBalancerRequest<T> request) throws IOException {
return this.execute(serviceId, (LoadBalancerRequest)request, (Object)null);
}
public <T> T execute(String serviceId, LoadBalancerRequest<T> request, Object hint) throws IOException {
//根据serviceId获得一个ILoadBalancer
ILoadBalancer loadBalancer = this.getLoadBalancer(serviceId);
//通过ILoadBalancer选择可用的服务器
Server server = this.getServer(loadBalancer, hint);
if(server == null) {
throw new IllegalStateException("No instances available for " + serviceId);
} else {
RibbonLoadBalancerClient.RibbonServer ribbonServer = new RibbonLoadBalancerClient.RibbonServer(serviceId, server, this.isSecure(server, serviceId), this.serverIntrospector(serviceId).getMetadata(server));
return this.execute(serviceId, (ServiceInstance)ribbonServer, (LoadBalancerRequest)request);
}
}
protected Server getServer(ILoadBalancer loadBalancer, Object hint) {
return loadBalancer == null?null:loadBalancer.chooseServer(hint != null?hint:"default");
}
@Bean
@ConditionalOnMissingBean
public ILoadBalancer ribbonLoadBalancer(IClientConfig config, ServerList<Server> serverList, ServerListFilter<Server> serverListFilter, IRule rule, IPing ping, ServerListUpdater serverListUpdater) {
return (ILoadBalancer)(this.propertiesFactory.isSet(ILoadBalancer.class, this.name)?(ILoadBalancer)this.propertiesFactory.get(ILoadBalancer.class, config, this.name):new ZoneAwareLoadBalancer(config, rule, ping, serverList, serverListFilter, serverListUpdater));
}
RibbonLoadBalancerClient.execute方法会调用另外一个execute重载方法,在这个方法中最终会调用LoadBalancerRequest.apply方法,而这个LoadBalancerRequest是在
LoadBalancerInterceptor.intercept方法中调用LoadBalancerRequestFactory.createRequest方法
创建的
public <T> T execute(String serviceId, ServiceInstance serviceInstance, LoadBalancerRequest<T> request) throws IOException {
Server server = null;
if(serviceInstance instanceof RibbonLoadBalancerClient.RibbonServer) {
//
server = ((RibbonLoadBalancerClient.RibbonServer)serviceInstance).getServer();
}
if(server == null) {
throw new IllegalStateException("No instances available for " + serviceId);
} else {
RibbonLoadBalancerContext context = this.clientFactory.getLoadBalancerContext(serviceId);
RibbonStatsRecorder statsRecorder = new RibbonStatsRecorder(context, server);
try {
Object ex = request.apply(serviceInstance);
statsRecorder.recordStats(ex);
return ex;
} catch (IOException var8) {
statsRecorder.recordStats(var8);
throw var8;
} catch (Exception var9) {
statsRecorder.recordStats(var9);
ReflectionUtils.rethrowRuntimeException(var9);
return null;
}
}
}
public LoadBalancerRequest<ClientHttpResponse> createRequest(HttpRequest request, byte[] body, ClientHttpRequestExecution execution) {
return (instance) -> {
Object serviceRequest = new ServiceRequestWrapper(request, instance, this.loadBalancer);
LoadBalancerRequestTransformer transformer;
if(this.transformers != null) {
for(Iterator var6 = this.transformers.iterator(); var6.hasNext(); serviceRequest = transformer.transformRequest((HttpRequest)serviceRequest, instance)) {
transformer = (LoadBalancerRequestTransformer)var6.next();
}
}
return execution.execute((HttpRequest)serviceRequest, body);
};
}
查看LoadBalancerRequestFactory.createRequest方法,创建了一个ServiceRequestWrapper,对HttpRequest做了封装,ServiceRequestWrapper重写了getURI方法,所以LoadBalancerRequest.apply会调用
ClientHttpRequestExecution.execute方法,即InterceptingClientHttpRequest.InterceptingRequestExecution.execute达到链式调用拦截器的目的,
public class ServiceRequestWrapper extends HttpRequestWrapper {
private final ServiceInstance instance;
private final LoadBalancerClient loadBalancer;
public ServiceRequestWrapper(HttpRequest request, ServiceInstance instance, LoadBalancerClient loadBalancer) {
super(request);
this.instance = instance;
this.loadBalancer = loadBalancer;
}
public URI getURI() {
URI uri = this.loadBalancer.reconstructURI(this.instance, this.getRequest().getURI());
return uri;
}
}
ServiceRequestWrapper.getURI方法调用了RibbonLoadBalancerClient.reconstructURI即RibbonLoadBalancerClient.reconstructURI方法,
public URI reconstructURI(ServiceInstance instance, URI original) {
Assert.notNull(instance, "instance can not be null");
String serviceId = instance.getServiceId();
RibbonLoadBalancerContext context = this.clientFactory.getLoadBalancerContext(serviceId);
URI uri;
Server server;
if(instance instanceof RibbonLoadBalancerClient.RibbonServer) {
RibbonLoadBalancerClient.RibbonServer clientConfig = (RibbonLoadBalancerClient.RibbonServer)instance;
server = clientConfig.getServer();
uri = RibbonUtils.updateToSecureConnectionIfNeeded(original, clientConfig);
} else {
server = new Server(instance.getScheme(), instance.getHost(), instance.getPort());
IClientConfig clientConfig1 = this.clientFactory.getClientConfig(serviceId);
ServerIntrospector serverIntrospector = this.serverIntrospector(serviceId);
uri = RibbonUtils.updateToSecureConnectionIfNeeded(original, clientConfig1, serverIntrospector, server);
}
return context.reconstructURIWithServer(server, uri);
}
最终调用LoadBalancerContext.reconstructURIWithServer对URI进行改写,改写的主要逻辑就是拿到LoadBalancer选择的服务器的host、port,和原请求的path,拼接成新的uri,完成改写,这样当正式发起http请求,会使用改写后的uri,完成具体的调用
public URI reconstructURIWithServer(Server server, URI original) {
String host = server.getHost();
int port = server.getPort();
String scheme = server.getScheme();
if(host.equals(original.getHost()) && port == original.getPort() && scheme == original.getScheme()) {
return original;
} else {
if(scheme == null) {
scheme = original.getScheme();
}
if(scheme == null) {
scheme = (String)this.deriveSchemeAndPortFromPartialUri(original).first();
}
try {
StringBuilder e = new StringBuilder();
e.append(scheme).append("://");
if(!Strings.isNullOrEmpty(original.getRawUserInfo())) {
e.append(original.getRawUserInfo()).append("@");
}
e.append(host);
if(port >= 0) {
e.append(":").append(port);
}
e.append(original.getRawPath());
if(!Strings.isNullOrEmpty(original.getRawQuery())) {
e.append("?").append(original.getRawQuery());
}
if(!Strings.isNullOrEmpty(original.getRawFragment())) {
e.append("#").append(original.getRawFragment());
}
URI newURI = new URI(e.toString());
return newURI;
} catch (URISyntaxException var8) {
throw new RuntimeException(var8);
}
}
}