RestTemplate拦截器原理及springcloud-ribbon的应用

1. RestTemplate

首先应清楚几个类的关系
RestTemplate extends InterceptingHttpAccessor implements RestOperations
public abstract class InterceptingHttpAccessor extends HttpAccessor
RestTemplate拦截器原理及springcloud-ribbon的应用_第1张图片
restTemplate进行API调用时,都会执行doExecute()方法

protected <T> T doExecute(URI url, HttpMethod method, RequestCallback requestCallback,
        ResponseExtractor<T> responseExtractor) throws RestClientException {
    ...
    ClientHttpResponse response = null;
    try {
        // 标记1
        ClientHttpRequest request = createRequest(url, method);
        if (requestCallback != null) {
            requestCallback.doWithRequest(request);
        }
        // 标记2
        response = request.execute();
        handleResponse(url, method, response);
        if (responseExtractor != null) {
            return responseExtractor.extractData(response);
        }
        else {
            return null;
        }
    }
    ...
}

再调用createRequest()方法

protected ClientHttpRequest createRequest(URI url, HttpMethod method) throws IOException {
    ClientHttpRequest request = getRequestFactory().createRequest(url, method);
    if (logger.isDebugEnabled()) {
        logger.debug("Created " + method.name() + " request for \"" + url + "\"");
    }
    return request;
}

扩展点就在getRequestFactory(),默认时SimpleClientHttpRequestFactory,如果getInterceptors()不为空,则返回InterceptingClientHttpRequestFactory类型的requestFactory。

private ClientHttpRequestFactory requestFactory = new SimpleClientHttpRequestFactory();

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

继续获取ClientHttpRequest,可以看到返回InterceptingClientHttpRequest,里面封装了interceptor。

@Override
protected ClientHttpRequest createRequest(URI uri, HttpMethod httpMethod, ClientHttpRequestFactory requestFactory) {
    return new InterceptingClientHttpRequest(requestFactory, this.interceptors, uri, httpMethod);
}

ClientHttpRequest获取到之后,执行标记2,通过一步步调用最终到以下代码,则会执行每个nextInterceptor.intercept(request, body, this)

private class InterceptingRequestExecution implements ClientHttpRequestExecution {
     

    private final Iterator 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 {
            ClientHttpRequest delegate = requestFactory.createRequest(request.getURI(), request.getMethod());
            for (Map.Entry> entry : request.getHeaders().entrySet()) {
                List values = entry.getValue();
                for (String value : values) {
                    delegate.getHeaders().add(entry.getKey(), value);
                }
            }
            if (body.length > 0) {
                StreamUtils.copy(body, delegate.getBody());
            }
            return delegate.execute();
        }
    }
}

2. springcloud的应用

@Bean
@LoadBalanced
public RestTemplate restTemplate() {
    return new RestTemplate();
}

使用@LoadBalanced注解后,springboot自动配置LoadBalancerAutoConfiguration,会将LoadBalancerInterceptor设入restTemplate的interceptors属性中。
回到[1]中,此时拿到的是InterceptingClientHttpRequestFactory,里面包装了所需要的LoadBalancerInterceptor。
回到[标记2]中,则会执行此方法:
org.springframework.cloud.client.loadbalancer.LoadBalancerInterceptor#intercept
之后便是springcloud-ribbon的客户端负载均衡逻辑了。

你可能感兴趣的:(springcloud,springcloud,resttemplate)