美文网首页
RestTemplate

RestTemplate

作者: __cbc | 来源:发表于2018-11-27 17:42 被阅读0次

      最近使用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);
            }
        }
    

    相关文章

      网友评论

          本文标题:RestTemplate

          本文链接:https://www.haomeiwen.com/subject/lylxqqtx.html