SpringBoot 中整合配置 RestTemplate

14,076 阅读3分钟

这是我参与2022首次更文挑战的第19天,活动详情查看:2022首次更文挑战

RestTemplate常用于访问HTTP端点的RESTful接口,SpringBoot 中提供简单快速的使用,同时也支持自定义配置相关连接参数。

RestTemplate 是 SpringBoot 提供的用于访问 RESTful 服务的客户端模板工具类,位于 org.springframework.web.client 包中。

1. 引入 RestTemplate

1.1 手动创建

创建一个RestTemplate对象,可以使用创建对象的方法来 new 一个实例对象,但是此种方法下的实例对象并不能交由 Spring 容器管理,此时并不能发挥 Spring 框架的作用。

RestTemplate restTemplate = new RestTemplate()

1.2 注解注入

SpringBoot 中内置了 RestTemlate 类并交由容器管理,因此对于同样交由容器管理的类,其中使用 restTemplate 对象时可以通过注解注入使用。

@Autowried
private RestTemplate restTemplate;

1.3 Could not autowire. No beans of 'RestTemplate' type found

如果直接使用注入的 restTemplate 对象,则会报错以上信息,并且提示 Consider defining a bean of type 'org.springframework.web.client.RestTemplate' in your configuration

出现此问题的原因是因为RestTemplate没有定义,也就是该对象没有实例化,在使用时到容器中无法找不到这个 bean 对象,此时只需要定义配置类来实现对象加入到容器中。

@Configuration
public class Config {
    @Bean
    public RestTemplate restTemplate(RestTemplateBuilder builder){
        return builder.build();
    }
}

需要注意的是:

  • SpringBoot1.3 版本之前并不需手动配置加入容器,SpringBoot 会自动定义 RestTemplate 并注入到容器
  • SpringBoot1.4 版本之后,SpringBoot 不再自定义 RestTemplate 注入,而是定义了一个RestTemplateBuilder,需要使用者进一步定义 RestTemplate
    • RestTemplateBuilder 对象的 build() 方法其本质就是使用 new RestTemplate() 来创建restTemplate 对象

2. 自定义配置 RestTemplate

SpringBoot 中对 RestTemplate 的各项参数有提供默认值,因此我们可以尽量少的配置进行使用,当然也可以根据需要自定义 RestTemplate 的生成配置。

2.1 定义HTTP客户端工厂类

通过客户端工厂类,可以定义 restTemplate 连接中使用的连接池、最大允许的连接数、连接超时时间等属性。

RestTemplate 是 SpringBoot 封装的请求工具类,其底层还是使用了 HttpClient,因此我们对 RestTemplate 的HTTP客户端工厂进行操作时,需要引入 HttpClient 依赖信息。

<dependency>
    <groupId>org.apache.httpcomponents</groupId>
    <artifactId>httpclient</artifactId>
</dependency>

配置HTTP连接池参数

@Bean
public HttpClientConnectionManager poolingConnectionManager() {
    // 连接池
    PoolingHttpClientConnectionManager poolingConnectionManager = new PoolingHttpClientConnectionManager();
    // 最大连接数
    poolingConnectionManager.setMaxTotal(1000);
    // 每个主机的并发
    poolingConnectionManager.setDefaultMaxPerRoute(100);
    // 空闲连接过期时间
    poolingConnectionManager.setValidateAfterInactivity(10_000);
}

创建HTTP工厂类

@Bean
public HttpClientBuilder createFactory() {
    HttpComponentsClientHttpRequestFactory httpRequestFactory = new HttpComponentsClientHttpRequestFactory();
    httpRequestFactory.setHttpClient(httpClientBuilder().build());
    //连接请求超时时间
    httpRequestFactory.setConnectionRequestTimeout(3000);
    //客户端和服务器建立连接的超时时间
    httpRequestFactory.setConnectTimeout(3000);
    //读取数据的超时时间
    httpRequestFactory.setReadTimeout(120000);
    return httpRequestFactory
}

最后,在创建 RestTemplete 对象时传入HTTP工厂类对象

RestTemplate restTemplate=new RestTemplate(httpRequestFactory);

2.2 使用 utf-8 字符集

RestTemplate 中的 StringHttpMessageConverter 转换器默认使用ISO-8859-1字符集,该字符集在转换中文字符时可能会导致乱码,因此可以修改为utf-8字符集。

// 获取restTemplate中的转换器集合
List<HttpMessageConverter<?>> converterList = restTemplate.getMessageConverters();

//遍历转换器集合,找到对应的StringHttpMessageConverter转换器
HttpMessageConverter<?> converterTarget = null;
for (HttpMessageConverter<?> item : converterList) {
    if (StringHttpMessageConverter.class == item.getClass()) {
        converterTarget = item;
        break;
    }
}

//如果存在目标转换器,则移除已有的
if (null != converterTarget) {
    converterList.remove(converterTarget);
}

//添加新的StringHttpMessageConverter转换器,并设置字符集为UTF-8
converterList.add(1, new StringHttpMessageConverter(StandardCharsets.UTF_8));

2.3 使用 fastjson 转换器

Spring 为RestTemplate 提供的json转换器是Jackson,该转换器要求json字符串与待转换的实体类严格对应,为了使用更加方便,可以将json转换器切换为阿里的fastJson。 使用fastjson需要先引入相关的依赖信息

<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>fastjson</artifactId>
    <version>1.2.54</version>
</dependency>

之后,便可以如切换String消息转换器一样,将原有转换器移除,将fastjson转换器加入。

//移除原有的json转换器
for (HttpMessageConverter<?> item : converterList) {
    if(converter instanceof GsonHttpMessageConverter || converter instanceof MappingJackson2HttpMessageConverter){
                    iterator.remove();
    }
}
//加入fastjson转换器
FastJsonHttpMessageConverter fastJsonHttpMessageConverter = new FastJsonHttpMessageConverter();
FastJsonConfig fastJsonConfig = new FastJsonConfig();
fastJsonConfig.setSerializerFeatures(
        SerializerFeature.WriteMapNullValue,
        SerializerFeature.WriteNullStringAsEmpty,
        SerializerFeature.WriteNullListAsEmpty,
        SerializerFeature.DisableCircularReferenceDetect);
fastJsonHttpMessageConverter.setFastJsonConfig(fastJsonConfig);
converterList.add(fastJsonHttpMessageConverter);

最后,返回restTemplate交给Spring容器管理,在使用时注入的对象就是自定义的restTemplate对象。