Related reading:

Sending AN HTTP request (1): There are several ways to send an HTTP request

Related components

RestTemplate is a client tool provided by Spring for accessing Rest services. It provides a variety of convenient methods for accessing remote Http services, which greatly improves client writing efficiency. RestTemplate is more of an integration framework than they are, a framework that can unify the way requests are sent.

Let’s take a look at the components

Inheritance system

RestTemplate inherits From InterceptingHttpAccessor and implements RestOperations

public class RestTemplate extends InterceptingHttpAccessor implements RestOperations {}Copy the code
RestOperations

A number of overloaded methods are used to define rest operations. For example, we often use

getForObject
postForObject
Copy the code
HttpAccessor

HttpAccessor provides the ClientHttpRequestFactory property for creating a ClientHttpRequest. The default initialization SimpleClientHttpRequestFactory factory class,

public abstract class HttpAccessor {
private ClientHttpRequestFactory requestFactory = newSimpleClientHttpRequestFactory(); . }Copy the code

On the request of several ways of section we said SimpleClientHttpRequestFactory for native JDK HttpURLConnection class factory. That is, RestTemplate uses HttpURLConnection to send HTTP requests by default.

However, we can set other factory classes using the set method. Use another way to send HTTP requests.

 public void setRequestFactory(ClientHttpRequestFactory requestFactory) {
        super.setRequestFactory(requestFactory);
        this.interceptingRequestFactory = null;
}
Copy the code
InterceptingHttpAccessor

InterceptingHttpAccessor inherits HttpAccessor. From its name, we can also tell that this is an HttpAccessor with interceptor functionality

public abstract class InterceptingHttpAccessor extends HttpAccessor {

	private List<ClientHttpRequestInterceptor> interceptors = new ArrayList<ClientHttpRequestInterceptor>();

	public void setInterceptors(List<ClientHttpRequestInterceptor> interceptors) {
		this.interceptors = interceptors;
	}

	public List<ClientHttpRequestInterceptor> getInterceptors(a) {
		return interceptors;
	}

	@Override
	public ClientHttpRequestFactory getRequestFactory(a) {
		ClientHttpRequestFactory delegate = super.getRequestFactory();
		if(! CollectionUtils.isEmpty(getInterceptors())) {return new InterceptingClientHttpRequestFactory(delegate, getInterceptors());
		}
		else {
			returndelegate; }}}Copy the code

GetRequestFactory () method, by judging whether interceptors, decision is created which has the function of intercepting InterceptingClientHttpRequestFactory, Or create a default SimpleClientHttpRequestFactory

Create ClientHttpRequest is InterceptingClientHttpRequest InterceptingClientHttpRequestFactory

Summary:

  • HttpAccessor: Provides support for the generic Http client ClientHttpRequest
  • InterceptingHttpAccessor: Provides support for ClientHttpRequest with intercepting functionality

Property system

The RestTemplate property also has several key components that we should understand.

RequestCallback

Callback interface for code that operates on a ClientHttpRequest. Allows to manipulate the request headers, and write to the request body. Used to manipulate the request header and body, executed before the request is issued.

ResponseExtractor

Parse the data of the HTTP Response and extract the data from the Response to extract the specified content from the ClientHttpResponse (such as the request header, the request Body, and so on)

UriTemplateHandler

Used to process: Path Param and Query Param

ResponseErrorHandler

Error response handler

Associated components

InterceptingRequestExecution

When we give Resttenplate set interceptor, the default will create a InterceptingClientHttpRequest client. When we call InterceptingClientHttpRequest. The execute () sends a request, will eventually call InterceptingClientHttpRequest. ExecuteInternal () method

@Override
	protected final ClientHttpResponse executeInternal(HttpHeaders headers, byte[] bufferedOutput) throws IOException {
	// Create a chain of interceptors based on interceptors.
		InterceptingRequestExecution requestExecution = new InterceptingRequestExecution();
		return requestExecution.execute(this, bufferedOutput);
	}
Copy the code

At this time to create an interceptor chain, and the current (this = InterceptingClientHttpRequest) passed as a parameter to perform in the chain.

ClientHttpRequestInterceptor

We look at how ClientHttpRequestInterceptor execution. InterceptingRequestExecution# the execute () will be executed first interceptors.

InterceptingRequestExecution class@Override
public ClientHttpResponse execute(HttpRequest request, byte[] body)  {
	if (this.iterator.hasNext()) {
		ClientHttpRequestInterceptor nextInterceptor = this.iterator.next();
		return nextInterceptor.intercept(request, body, this); }... }Copy the code

Interceptor execution chain, get an interceptor, execute its Intercept method. Execution. Execute () is called in each Intercept method to form a chained call.

Request process

With components out of the way, let’s talk about the implementation process using getForObject as an example

@Override
	public <T> T getForObject(String url, Class<T> responseType, Object... urlVariables) throws RestClientException {
		RequestCallback requestCallback = acceptHeaderRequestCallback(responseType);
		HttpMessageConverterExtractor<T> responseExtractor =
				new HttpMessageConverterExtractor<T>(responseType, getMessageConverters(), logger);
		return execute(url, HttpMethod.GET, requestCallback, responseExtractor, urlVariables);
	}
	public <T> T execute(String url, HttpMethod method, RequestCallback requestCallback, ResponseExtractor
       
         responseExtractor, Object... urlVariables)
        throws RestClientException {

		URI expanded = getUriTemplateHandler().expand(url, urlVariables);
		return doExecute(expanded, method, requestCallback, responseExtractor);
	}
Copy the code

Call the doExecute method

protected <T> T doExecute(URI url, HttpMethod method, RequestCallback requestCallback, ResponseExtractor
       
         responseExtractor)
        throws RestClientException {
		ClientHttpResponse response = null;
		try {
		// Create an HTTP request client according to
			ClientHttpRequest request = createRequest(url, method);
			if(requestCallback ! =null) {
			// If requestCallback is not null. With the request
				requestCallback.doWithRequest(request);
			}
			// Execute the request
			response = request.execute();
			// Handle requests, including error response handling
			handleResponse(url, method, response);
			// Specify data in advance
			if(responseExtractor ! =null) {
				return responseExtractor.extractData(response);
			}
			else {
				return null; }}...finally {
			if(response ! =null) { response.close(); }}}Copy the code
  1. First get the RequestCallback,ResponseExtractor tools. And calls UriTemplateHandler to handle arguments in the URL
  2. Get a ClientHttpRequest from HttpAccessor, if the configuration ClientHttpRequestInterceptor, By InterceptingClientHttpRequestFactory created which has the function of the interceptor InterceptingClientHttpRequest client. If there is no use common ClientHttpRequestFactory create a common client, use HttpURLConnection SimpleClientHttpRequestFactory created by default the client
  3. After getting ClientHttpRequest, if RequestCallback is not null. Execute RequestCallback
  4. Perform ClientHttpRequest. The execute (). If there are ClientHttpRequestInterceptor, execute ClientHttpRequestInterceptor first, then send the request.
  5. ResponseErrorHandler Handles possible error responses
  6. If a responseExtractor response extractor exists, the responseExtractor is called to extract the response data.
  7. The data returned

conclusion

The Resttemplate is supposed to be an abstraction of the way requests are sent; it does not produce the request, but merely consolidates it. The result of this advanced integration is a much easier and richer way to send requests.

Recommended reading:

SpringCloud source code read 0-SpringCloud essential knowledge

SpringCloud source code read 1-EurekaServer source code secrets

SpringCloud source code read 2-Eureka client secrets

3 Ribbon Load Balancing

4 Ribbon Load Balancing

Welcome everyone to pay attention to my public number [source code action], the latest personal understanding timely.