RestTemplate使用

前言

在 SpringBoot 中,去除了很多繁杂的配置,而使用公用的配置和模块来集成类似的功能,在 SpringBoot3.0 引入的 RestTemplate 即是典型的对于同步的请求做了统一的封装(异步请求 AsyncRestTemplate 已经废弃,建议使用 SpringBoot5.0 的 WebClient),前几天看了同事的代码,发现对于 RestTemplate 的使用理解还差点,正好研究下

execute 介绍

先说一下这个方法,观察平时使用的各种请求方式最终都会落到这个重载的 doExecute 方法上来
默认情况下,整个流程是

  1. 创建 RestTemplate 对象,载入默认的各种消息处理器,ClientHttpRequestFactory 和 UriTemplate
  2. 根据传入的参数,使用 ClientHttpRequestFactory 根据 URL 和 Method 来创建请求,并设置 Header
  3. 执行请求操作,异常情况使用默认的异常处理器处理,默认使用的是 JDK 自带的 HttpClient 请求,正常情况下会根据 Header 中的 ContentType 属性或者接收对象类型来确定使用具体的消息转换器来处理信息,最后包装响应体,返回响应结果

基本使用

虽然实际使用方法多,但都是根据请求方法和响应体类型区分而已,所以具体使用起来并不复杂
根据请求类型分,有 GET、POST、PUT、DELETE、PATCH、OPTION、HEAD 七种请求方式
根据参数也能分为直接 String 字符串,Object 对象形式和 LinkedMap 形式的表单提交方式
根据返回体类型,可以分为 xxxForObject,xxxForEntity,exchange 方法,第一个是直接返回响应体中的 Body 属性,第二个返回的是 HttpEntity,包含有状态码和响应头,Exchange 方法就可以自定定义请求方式了

自定义 RestTemplate 设置

如前所述,整个流程的消息转换器、异常处理器、Http 请求框架和请求属性设置都可以自定义

自定义消息转换器

默认 Spring 使用的处理 Json 数据的是MappingJackson2HttpMessageConverter,我也是偏向于使用 jackson 相关序列化工具,如果想要使用其他序列化工具在AbstractHttpMessageConverter抽象类下有多种消息转换器,对于 Jackson 我们可以设置 ObjectMapper 来自定义序列化配置,这里就没配上了,生产中则最好配上统一的配置

1
2
3
4
5
6
7
8
9
10
11
12
13
@Bean
public RestTemplate restTemplate() {
RestTemplate restTemplate = new RestTemplate();
//设置自定义的异常处理器
restTemplate.setErrorHandler(new RestTemplateExceptionHandler());
//设置自定义拦截器
restTemplate.setInterceptors(Collections.singletonList(interceptor));
//设置自定义消息转换器
restTemplate.setMessageConverters(Collections.singletonList(mappingJacksonHttpMessageConverter()));
//替换HttpS实现
return restTemplate;

}
1
2
3
4
5
6
7
8
9
10
11
@Bean
public MappingJackson2HttpMessageConverter mappingJacksonHttpMessageConverter() {
MappingJackson2HttpMessageConverter converter = new MappingJackson2HttpMessageConverter();
converter.setObjectMapper(restTemplateObjectMapper());
return converter;
}

@Bean
public ObjectMapper restTemplateObjectMapper() {
return new ObjectMapper();
}

自定义拦截器

一般都用来记录日志

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
@Component
@Slf4j
public class RestTemplateInterceptor implements ClientHttpRequestInterceptor {

@Override
@NonNull
public ClientHttpResponse intercept(HttpRequest request, @Nonnull byte[] body, ClientHttpRequestExecution execution) throws IOException {
Assert.notNull(request.getURI(), "请求路径不能为空");
Assert.notNull(request.getMethod(), "请求方法不能为空");
String rawPath = request.getURI().getRawPath();
String name = request.getMethod().name();
log.info("【RestTemplate请求】请求路径:{}, 请求方法:{}", rawPath, name);
return execution.execute(request, body);
}
}

自定义异常处理器

一般会指定相关的错误码和错误信息

1
2
3
4
5
6
7
8
9
@Slf4j
public class RestTemplateExceptionHandler extends DefaultResponseErrorHandler {

@Override
public void handleError(URI url, HttpMethod method, @Nullable ClientHttpResponse response) {
log.error("RestTemplate请求异常, url:{}, 请求方式:{}, 响应信息:{}", url.getPath(), method.name(), JsonUtil.toJson(response));
throw new BusinessException(ExceptionEnum.REST_TEMPLATE_EXCEPTION);
}
}

替换 Http 请求组件&设置连接属性

在 SpringBoot 中请求创建都是通过ClientHttpRequestFactory来创建的,所以设置连接属性也是在这里设置,默认使用的 HttpClient 连接具体实现是SimpleClientHttpRequestFactory,若想使用其他 Http 组件来创建连接则需要新建新的ClientHttpRequestFactory来获取,比如 okHttp 对应的即为OkHttp3ClientHttpRequestFactory

1
2
3
4
5
6
7
@Bean
public ClientHttpRequestFactory simpleClientHttpRequestFactory() {
SimpleClientHttpRequestFactory factory = new SimpleClientHttpRequestFactory();
factory.setReadTimeout(1000);
factory.setConnectTimeout(6000);
return factory;
}
作者

孙博文

发布于

2020-08-23

更新于

2021-07-18

许可协议

评论