RestTemplate

2018-11-27  本文已影响0人  __cbc

  最近使用restTemplate的时候遇到了很多问题,在排查问题的时候了解了下其中的源码。(这块没有文档,真的难受。)

spring boot 提供了RestTemplate自动配置类 RestTemplateAutoConfiguration。

@Configuration
@AutoConfigureAfter(HttpMessageConvertersAutoConfiguration.class)
@ConditionalOnClass(RestTemplate.class)
public class RestTemplateAutoConfiguration {

private final ObjectProvider<HttpMessageConverters> messageConverters;

   private final ObjectProvider<RestTemplateCustomizer> restTemplateCustomizers;

   public RestTemplateAutoConfiguration(
           ObjectProvider<HttpMessageConverters> messageConverters,
           ObjectProvider<RestTemplateCustomizer> restTemplateCustomizers) {
       this.messageConverters = messageConverters;
       this.restTemplateCustomizers = restTemplateCustomizers;
   }
……
} 

这里看到这个类是在消息转换器自动配置之后配置的,我们观察到spring 注入属性的时候用到了ObjectProvider这个类,这个类是spring 4.3出来的新特性,spring 4之后推荐构造函数注入,并且在4.3之后可以使用构造函数隐式注入,即如果没有在构造函数上加@Autowired,spring会从使用改类中默认的构造器注入,当然如果多个构造器就必须加上此注解了。ObjectProvider(spring里面为BeanObjectProvider)这个类解决了bean为空,和bean有多个实例的问题,里面包含getObject、getIfAvailable、getIfUnique等方法。

    @Bean
    @ConditionalOnMissingBean
    public RestTemplateBuilder restTemplateBuilder() {
        RestTemplateBuilder builder = new RestTemplateBuilder();
        HttpMessageConverters converters = this.messageConverters.getIfUnique();
        if (converters != null) {
            builder = builder.messageConverters(converters.getConverters());
        }

        List<RestTemplateCustomizer> customizers = this.restTemplateCustomizers
                .orderedStream().collect(Collectors.toList());
        if (!CollectionUtils.isEmpty(customizers)) {
            builder = builder.customizers(customizers);
        }
        return builder;
    }

这个方法会构造一个RestTemplateBuilder交给spring管理,中间通过getIfUnique()获取到单例的HttpMessageConverters 和restTemplateCustomizers,把其中所有自动配置的消息转换器和所有的RestTemplateCustomizer(用于自定义restTemplate的回调接口)加入这个RestTemplateBuilder,然后返回一个完整的实例。当然方法首先new了一个RestTemplateBuilder,看看它的构造器给我们干了什么。

    public RestTemplateBuilder(RestTemplateCustomizer... customizers) {
        Assert.notNull(customizers, "Customizers must not be null");
        this.detectRequestFactory = true;
        this.rootUri = null;
        this.messageConverters = null;
        this.requestFactorySupplier = null;
        this.uriTemplateHandler = null;
        this.errorHandler = null;
        this.basicAuthentication = null;
        this.restTemplateCustomizers = Collections
                .unmodifiableSet(new LinkedHashSet<>(Arrays.asList(customizers)));
        this.requestFactoryCustomizer = new RequestFactoryCustomizer();
        this.interceptors = Collections.emptySet();
    }

这里给detectRequestFactory赋值成了true,目的是为了后面自动检测ClientHttpRequestFactory。

接下来我们使用的时候通常会将RestTemplateBuilder注入到要使用到bean里面,使用之前spring自动配置给我们带来的功能,并且我们可以附加很多功能,比如自定义 的HttpMessageConverter、自定义的RestTemplate、自定义的ClientHttpRequestFactory、自定义的异常处理和请求拦截器。

最终的目的是为了得到一个供我们使用的RestTemplate。我们通常会使用build()方法构建。 接下来看看build方法做了什么。

    public RestTemplate build() {
        return build(RestTemplate.class);
    }

    /**
     * Build a new {@link RestTemplate} instance of the specified type and configure it
     * using this builder.
     * @param <T> the type of rest template
     * @param restTemplateClass the template type to create
     * @return a configured {@link RestTemplate} instance.
     * @see RestTemplateBuilder#build()
     * @see #configure(RestTemplate)
     */

    public <T extends RestTemplate> T build(Class<T> restTemplateClass) {
        return configure(BeanUtils.instantiateClass(restTemplateClass));
    }

在我们没有自定义RestTemplate我们会调用上面方法,他会调用下面方法,帮我们创建一个RestTemplate的实例作为configure的参数,再来看configure方法:

public <T extends RestTemplate> T configure(T restTemplate) {
        configureRequestFactory(restTemplate);
        if (!CollectionUtils.isEmpty(this.messageConverters)) {
            restTemplate.setMessageConverters(new ArrayList<>(this.messageConverters));
        }
        if (this.uriTemplateHandler != null) {
            restTemplate.setUriTemplateHandler(this.uriTemplateHandler);
        }
        if (this.errorHandler != null) {
            restTemplate.setErrorHandler(this.errorHandler);
        }
        if (this.rootUri != null) {
            RootUriTemplateHandler.addTo(restTemplate, this.rootUri);
        }
        if (this.basicAuthentication != null) {
            restTemplate.getInterceptors().add(this.basicAuthentication);
        }
        restTemplate.getInterceptors().addAll(this.interceptors);
        if (!CollectionUtils.isEmpty(this.restTemplateCustomizers)) {
            for (RestTemplateCustomizer customizer : this.restTemplateCustomizers) {
                customizer.customize(restTemplate);
            }
        }
        return restTemplate;
    }

这里就是把刚刚自动配置的消息转换器,错误处理器,配置一些URI模板,URI路径的模板,发送请求的basic认证拦截器和其他一些拦截器(ClientHttpRequestInterceptor),一些自定义的restTemplate的会调接口。

然后继续看其中的

configureRequestFactory(restTemplate);
    private void configureRequestFactory(RestTemplate restTemplate) {
        ClientHttpRequestFactory requestFactory = null;
        if (this.requestFactorySupplier != null) {
            requestFactory = this.requestFactorySupplier.get();
        }
        else if (this.detectRequestFactory) {
            requestFactory = new ClientHttpRequestFactorySupplier().get();
        }
        if (requestFactory != null) {
            if (this.requestFactoryCustomizer != null) {
                this.requestFactoryCustomizer.accept(requestFactory);
            }
            restTemplate.setRequestFactory(requestFactory);
        }
    }
上一篇下一篇

猜你喜欢

热点阅读