spring

SpringCloud解析一:RestTemplate源码分析

2019-12-19  本文已影响0人  一根线条

在我们使用Spring框架进行应用开发的时候,RestTemplate组件的使用越来越频繁,在这里我简单的梳理下它的源码,从而更深入的理解其工作原理,同时也为后面的Ribbon的使用打下基础。

首先我们从一张较为简洁的类图开始,从全局了解其继承关系

RestTemplate继承关系

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在执行调用的时候主要就是经过了以下三步

  1. 使用ClientHttpRequestFactory类型对象创建ClientHttpRequest类型对象【例如可以执行拦截器的 InterceptingClientHttpRequest 】
  2. 执行ClientHttpRequest类型实例对象的execute()方法得到ClientHttpResponse类型的响应结果
  3. 对响应结果进行处理并返回给调用者

小结

通过以上的分析,应该已经可以很好的理解RestTemplate的执行原理了,我们也可以通过自定义RequestFactory和拦截器的方式来扩展其功能,例如使用RestTemplate完成客户端负载均衡等。最后提供一张较为完整的类图,供大家参考


RestTemplate类图
上一篇下一篇

猜你喜欢

热点阅读