tags: [RestTemplate]
categories: [springboot]


前言

在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. @Bean
  2. public RestTemplate restTemplate() {
  3. RestTemplate restTemplate = new RestTemplate();
  4. //设置自定义的异常处理器
  5. restTemplate.setErrorHandler(new RestTemplateExceptionHandler());
  6. //设置自定义拦截器
  7. restTemplate.setInterceptors(Collections.singletonList(interceptor));
  8. //设置自定义消息转换器
  9. restTemplate.setMessageConverters(Collections.singletonList(mappingJacksonHttpMessageConverter()));
  10. //替换HttpS实现
  11. return restTemplate;
  12. }
  1. @Bean
  2. public MappingJackson2HttpMessageConverter mappingJacksonHttpMessageConverter() {
  3. MappingJackson2HttpMessageConverter converter = new MappingJackson2HttpMessageConverter();
  4. converter.setObjectMapper(restTemplateObjectMapper());
  5. return converter;
  6. }
  7. @Bean
  8. public ObjectMapper restTemplateObjectMapper() {
  9. return new ObjectMapper();
  10. }

自定义拦截器

一般都用来记录日志

  1. @Component
  2. @Slf4j
  3. public class RestTemplateInterceptor implements ClientHttpRequestInterceptor {
  4. @Override
  5. @NonNull
  6. public ClientHttpResponse intercept(HttpRequest request, @Nonnull byte[] body, ClientHttpRequestExecution execution) throws IOException {
  7. Assert.notNull(request.getURI(), "请求路径不能为空");
  8. Assert.notNull(request.getMethod(), "请求方法不能为空");
  9. String rawPath = request.getURI().getRawPath();
  10. String name = request.getMethod().name();
  11. log.info("【RestTemplate请求】请求路径:{}, 请求方法:{}", rawPath, name);
  12. return execution.execute(request, body);
  13. }
  14. }

自定义异常处理器

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

  1. @Slf4j
  2. public class RestTemplateExceptionHandler extends DefaultResponseErrorHandler {
  3. @Override
  4. public void handleError(URI url, HttpMethod method, @Nullable ClientHttpResponse response) {
  5. log.error("RestTemplate请求异常, url:{}, 请求方式:{}, 响应信息:{}", url.getPath(), method.name(), JsonUtil.toJson(response));
  6. throw new BusinessException(ExceptionEnum.REST_TEMPLATE_EXCEPTION);
  7. }
  8. }

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

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

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