场景描述

restTemplate 是 spring 提供的基于 restful 设计的 http 请求客户端。

使用介绍

配置

springboot 默认提供了 restTemplate 相关的 Bean,但也可以通过手动注册同类型的 bean 来自定义一些配置,如通用的请求头,拦截器等。

1
2
3
4
5
6
@Bean
public RestTemplate restTemplate(ClientHttpRequestFactory factory) {
RestTemplate restTemplate = new RestTemplate(factory);
// 其他设置,如:拦截器、消息处理器等
return restTemplate;
}

拦截器

一般的会将特定功能的拦截器,注册到独立的 restTemplate bean 中,即设置多个 restTemplate bean(默认同类型下只能存在一个 bean,可以使用包装类,装饰器)。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
// 定义自定义拦截器
public class CustomInterceptor implements ClientHttpRequestInterceptor
{
@Override
public ClientHttpResponse intercept(HttpRequest request, byte[] body, ClientHttpRequestExecution execution) throws IOException
{
// 自定义方法体
...
// 执行完毕后放行请求
return execution.execute(request, body);
}
}
// 添加拦截器
restTemplate.getInterceptors().add(new CustomInterceptor())

自定义消息转换器

项目中经常使用 FastJson 替换 Jackson,实际上项目中存在一个 Json 处理工具即可,(Jackson 挺好用的,感觉 Bug 少多了)。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
public void setRestTemplate(RestTemplate restTemplate) {
// 重新设置了消息转换器集合,通过遍历过滤了原有的 Jackson 处理器,最后添加了 FastJson 处理器
// 也可以直接在原有的 list 中使用 remove 去除,再添加
List<HttpMessageConverter<?>> converters = restTemplate.getMessageConverters();
List<HttpMessageConverter<?>> convertersValid = new ArrayList<>();
for (HttpMessageConverter<?> converter : converters) {
if (converter instanceof MappingJackson2HttpMessageConverter
|| converter instanceof MappingJackson2XmlHttpMessageConverter) {
continue;
}
convertersValid.add(converter);
}
convertersValid.add(fastJsonHttpMessageConverter());
restTemplate.setMessageConverters(convertersValid);
}

/**
* fastJson 消息转换器
*
* @return fastJson 消息转换器
*/
private FastJsonHttpMessageConverter fastJsonHttpMessageConverter() {
List<MediaType> mediaTypes = new ArrayList<>();
mediaTypes.add(MediaType.APPLICATION_JSON);
FastJsonConfig fastJsonConfig = new FastJsonConfig();
fastJsonConfig.setSerializerFeatures(SerializerFeature.DisableCircularReferenceDetect,
SerializerFeature.WriteMapNullValue,
SerializerFeature.WriteDateUseDateFormat);
fastJsonConfig.setDateFormat("yyyy-MM-dd HH:mm:ss");
GsonHttpMessageConverter gsonHttpMessageConverter = new GsonHttpMessageConverter();
gsonHttpMessageConverter.setSupportedMediaTypes(mediaTypes);
FastJsonHttpMessageConverter fastConverter = new FastJsonHttpMessageConverter();
fastConverter.setSupportedMediaTypes(mediaTypes);
fastConverter.setFastJsonConfig(fastJsonConfig);
return fastConverter;
}

Get 参数设置

使用 restful 占位符,设置方式和 controller 层一致,如:

1
2
3
4
5
6
7
void testGetParam() {
restTemplate.getForObject(
'route?param1={param1}&param2={param2}',
T.class,
...参数
)
}

ps:当然参数也可以使用 Map

List 类型结果

对于任意使用 List 的结果集,在泛型类型设置上,使用 T[].class 替代,可以很好的避免 List<?> 无法获取具体类型的问题。
当然也可以使用 new ParameterizedTypeReference<List<T>>(){},但其本身是通过生成匿名类(类中的泛型不会被擦除)的方式来记录泛型信息。
使用数组类型无疑更简洁优雅。

自定义 header

使用 exchange 方法

1
2
3
4
5
6
7
8
9
10
11
void testExchange() {
HttpHeaders requestHeaders = new HttpHeaders();
HttpEntity<UserModel[]> request = new HttpEntity<>(requestHeaders);
val result = restTemplate.exchange(
"路由",
HttpMethod.GET,
request,
T[].class,
...参数
).getBody();
}

使用 execute 方法

1
2
3
4
5
6
7
8
9
10
11
12
13
void testExecute() {
HttpHeaders requestHeaders = new HttpHeaders();
HttpEntity<UserModel[]> request = new HttpEntity<>(requestHeaders);
val requestCallback = restTemplate.httpEntityCallback(request, T[].class);
val responseExtractor = restTemplate.responseEntityExtractor(T[].class);
val result = restTemplate.execute(
"路由",
HttpMethod.GET,
requestCallback,
responseExtractor,
...参数
);
}

评论