RestTemplate

  最近使用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);
        }
    }
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 136,677评论 19 139
  • Spring Boot 参考指南 介绍 转载自:https://www.gitbook.com/book/qbgb...
    毛宇鹏阅读 47,283评论 6 342
  • 1.1 spring IoC容器和beans的简介 Spring 框架的最核心基础的功能是IoC(控制反转)容器,...
    simoscode阅读 6,852评论 2 22
  • Spring Web MVC Spring Web MVC 是包含在 Spring 框架中的 Web 框架,建立于...
    Hsinwong阅读 22,966评论 1 92
  • 1、不脱嫌热,脱后嫌冷,此乃春天。 2、不送不安,送后不廉,此乃春节。 3、不看失落,看后失望,此乃春晚。 4、不...
    Stephen潇雨阅读 281评论 0 0

友情链接更多精彩内容