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
- First get the RequestCallback,ResponseExtractor tools. And calls UriTemplateHandler to handle arguments in the URL
- 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
- After getting ClientHttpRequest, if RequestCallback is not null. Execute RequestCallback
- Perform ClientHttpRequest. The execute (). If there are ClientHttpRequestInterceptor, execute ClientHttpRequestInterceptor first, then send the request.
- ResponseErrorHandler Handles possible error responses
- If a responseExtractor response extractor exists, the responseExtractor is called to extract the response data.
- 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.