努力学习,努力冲

关于后端微服务通信中RestTemplate的三种创建方式(RestTemplateBuilder,RestTemplateCustomizer)

一.关于RestTemplate的三种创建方式

最早接触RestTemplate是学到微服务间服务的通信使用http的rest风格在应用层进行通信,不过视频讲的很少,我就决定自己做一个总结,不过由于没有接触过restTemplate请求中发送cookie或者jwt等,所以业务方面可能写的简单点.
RestTemplate的主要三种配置方式有

  • 使用RestTemplateBuilder来配置超时信息
  • 使用RestTemplateCustomizer来自定义化配置
  • 使用RestTemplateCustomizer和RestTemplateBuilder结合配置

1.使用RestTemplateBuilder来进行配置

下图是springApi 2.7.3关于RestTemplateBuilder的解释

图片.png
大致意思:restTemplateBuilder是一个生成restTemplate的类,可以很方便的注册errorHandler,MessageConverts,URL模板,超时时间的设置等,同时这个类会被自动注册为bean,你可以在需要的地方直接注入。

下面是一个简单的使用:

复制代码
@Configuration
public class BaseConfiguration {
@Autowired
LoadBalancerClient loadBalancerClient;
@Bean
public RestTemplate restTemplate(RestTemplateBuilder restTemplateBuilder){
return restTemplateBuilder
.additionalInterceptors(new LoadBalancerInterceptor(loadBalancerClient))
.setConnectTimeout(Duration.ofSeconds(5))
.build();
}

2.使用RestTemplateCustomizer来自定义

Customizer的意思本身就是定制器,我们查看springAPi的解释:

图片.png

值得一提的是,RestTemplatecustomizer分别在两个包中都有定义,分别是:
1.org.springframework.boot.web.client.RestTemplateCustomizer;
2.org.springframework.cloud.client.loadbalancer.RestTemplateCustomizer
按照boot api的定义,我认为是通过RestTemplateCustomizer来定义的,两个接口的内部方法差不多,第二个的官方文档没有找到,决定使用第一个

官方api的意思翻译过来就是:通过实现这个接口的customize(RestTemplate restTemplate)这个回调函数,可以给RestTemplate进行定制。
下面是简单的使用:
一个简单的拦截器:

复制代码
// 自定义一个简单的拦截器
package com.interceptor;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.HttpRequest;
import org.springframework.http.client.ClientHttpRequestExecution;
import org.springframework.http.client.ClientHttpRequestInterceptor;
import org.springframework.http.client.ClientHttpResponse;
import java.io.IOException;
public class CustomRestTemplateCustomizerInterceptor implements ClientHttpRequestInterceptor {
private static final Logger logger = LoggerFactory.getLogger(CustomRestTemplateCustomizerInterceptor.class);
@Override
public ClientHttpResponse intercept(HttpRequest request, byte[] body, ClientHttpRequestExecution execution) throws IOException {
logDetails(request);
return execution.execute(request, body);
}
public void logDetails(HttpRequest request){
logger.info("url:{}",request.getURI());
logger.info("method:{}",request.getMethod());
logger.info("header:{}",request.getHeaders());
}
}

回调函数中添加进去这个拦截器

复制代码
package com.bean;
import com.interceptor.CustomRestTemplateCustomizerInterceptor;
import org.springframework.boot.web.client.RestTemplateCustomizer;
import org.springframework.web.client.RestTemplate;
public class CustomRestTemplateCustomizer implements RestTemplateCustomizer {
@Override
public void customize(RestTemplate restTemplate) {
// 自定制interceptor
restTemplate.getInterceptors().add(new CustomRestTemplateCustomizerInterceptor());
}
}

将我们写的定制器注册为bean

复制代码
@Bean
public CustomRestTemplateCustomizer customRestTemplateCustomizer(){
return new CustomRestTemplateCustomizer();
}

运行试试:

图片.png
可以看到我们的通过定制器自定义的拦截器起了作用。

3.使用RestTemplateCustomizer和RestTemplateBuilder结合配置

这是一个破坏性最大,也是定制性最高的方式,至于破坏性,我们在后面说,先来说一说这种的如何配置

复制代码
@Bean
@DependsOn({"customRestTemplateCustomizer"})
public RestTemplateBuilder restTemplateBuilder(CustomRestTemplateCustomizer customRestTemplateCustomizer){
RestTemplateBuilder restTemplateBuilder = new RestTemplateBuilder(customRestTemplateCustomizer);
System.out.println("添加了定制器的"+restTemplateBuilder);
return restTemplateBuilder;
}

这种配置是将定制器作为参数传入到RestTemplateCustomizer的构造方法中去。

疑问1:我们构造为bean的RestTemplateCustomizer会不会和自动构造的(前文有提到)RestTemplateCustomizer产生冲突还是覆盖?
实验1:
代码:

复制代码
@Configuration
public class BaseConfiguration {
@Autowired
LoadBalancerClient loadBalancerClient;
@Bean
public RestTemplate restTemplate(RestTemplateBuilder restTemplateBuilder){
// mark1
System.out.println("这是第一个方法里面的"+restTemplateBuilder);
return restTemplateBuilder
.additionalInterceptors(new LoadBalancerInterceptor(loadBalancerClient))
.setConnectTimeout(Duration.ofSeconds(5))
.build();
}
@Bean
public CustomRestTemplateCustomizer customRestTemplateCustomizer(){
return new CustomRestTemplateCustomizer();
}
@Bean
@DependsOn({"customRestTemplateCustomizer"})
public RestTemplateBuilder restTemplateBuilder(CustomRestTemplateCustomizer customRestTemplateCustomizer){
RestTemplateBuilder restTemplateBuilder = new RestTemplateBuilder(customRestTemplateCustomizer);
// mark2
System.out.println("添加了定制器的"+restTemplateBuilder);
return restTemplateBuilder;
}
}

我们看到写了两个mark标记,查看这两个是不是同一个RestTemplateBuilder。
运行查看输出:

图片.png
我们可以看到这里我们自己构造的RestTemplateBuilder完全覆盖了框架提供的RestTemplateBuilder。

疑问2:为什么说这种方式的破坏性极大
实验2:我们首先不定制,打断点之后查看框架提供的RestTemplateBuilder有哪些属性:

图片.png

图片.png
这是不自定义得到的框架提供的RestTemplateBuilder,我们可以看到有许多的消息转换器

我们通过刚刚的代码定制覆盖之后查看缺少了那些属性:

图片.png
我们可以看到缺少了消息转换器以及定制器的数量也发生了变化。

以上就是三种不同的生成RestTemplate的方式。

RestTemplate的原理以及代码解析:暂时写作中

posted @   写不完作业还要玩  阅读(2412)  评论(0)    收藏  举报
点击右上角即可分享
微信分享提示