敞开生长之旅!这是我参与「日新计划 12 月更文挑战」的第4天,点击查看活动概况

庾信平生最萧条,老年诗赋动江关

欢迎重视【架构染色】沟通学习

开篇

Feign 是声明式、模板化的 HTTP 客户端, 能够协助咱们更方便、优雅地调用 HTTP API;Spring Cloud 为 Feign 添加了 Spring MVC 的注解支撑,并整合了 Ribbon 和 Eureka 来为运用 Feign 时供给负载均衡;在 Spring Cloud 中运用 Feign 是非常简单的。

本篇首要介绍 SpringBoot 中要玩转 Feign 需要把握的如添加 pom 依靠、客户端注解启用、切换底层 HttpClient、装备数据紧缩、调整日志等级、定制装备、装备的优先级机制、添加拦截器以及拦截器的追加机制等常识。

一、运用 Feign 的示例

1.1 添加依靠

<dependencies>
<!--openfein的依靠-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
<version>2.1.3.RELEASE</version>
</dependency>
</dependencies>

1.2 启用 Feign

在 SpringBoot 的启用类上添加注解@EnableFeignClients@EnableFeignClients用于敞开 Feign,会主动扫描@FeignClient标注的 FeignClient 接口。

@SpringBootApplication
@EnableFeignClients
@EnableWeb
publicclassFeignApplication{
publicstaticvoidmain(String[]args){
SpringApplication.run(FeignApplication.class,args);
}
}

1.3 编写 FeignClient 接口

@FeignClient(
name="demo-service",
url="http://localhost:8080/feign/server/",
configuration=FeignInterceptor.class,
fallback=TestService.DefaultFallback.class
)
publicinterfaceTestService{
@RequestMapping(value="/getError/{id}",method=RequestMethod.GET)
publicStringgetError(@RequestParam("id")Integerid);
@RequestMapping(value="/get1",method=RequestMethod.GET)
publicStringget1();
@RequestMapping(value="/get2/{param}",method=RequestMethod.GET)
publicStringget2(@RequestParam("param")Stringparam);
@RequestMapping(value="/post1",method=RequestMethod.POST)
publicFeignDemopost1(@RequestBodyFeignDemodemo);

1.4 编写对应的服务端

@RestController
@RequestMapping("/feign/server")
publicclassFeignServerController{
@GetMapping("/get1")
publicStringget1(){
return"get1";
}
@GetMapping("/get2/{para}")
publicStringget2(@PathVariable("para")Stringpara){
returnpara;
}
@PostMapping("/post1")
publicFeignDemopost1(@RequestBodyFeignDemodemo){
returndemo;
}
}
publicclassFeignDemo{
privateStringname;
privateIntegerage;
publicStringgetName(){
returnname;
}
publicvoidsetName(Stringname){
this.name=name;
}
publicIntegergetAge(){
returnage;
}
publicvoidsetAge(Integerage){
this.age=age;
}
@Override
publicStringtoString(){
return"FeignDemo{"+
"name='"+name+'''+
",age="+age+
'}';
}
}

1.5 调用 FeignClient

@RunWith(SpringJUnit4ClassRunner.class)
@SpringBootTest(classes={FeignApplication.class},webEnvironment=SpringBootTest.WebEnvironment.DEFINED_PORT)
@ActiveProfiles("dev,feign")
publicclassFeignClientTest{
@Autowired
privateTestServicetestService;
@Test
publicvoidtestFallback(){
testService.getError(1);
}
@Test
publicvoidtestGet1(){
System.out.println(testService.get1());
System.out.println(testService.get2("abc"));
System.out.printf("..");
FeignDemofeignDemo=newFeignDemo();
feignDemo.setName("name");
feignDemo.setAge(1);
System.out.println(testService.post1(feignDemo));
}
@Component
publicclassDefaultFallbackimplementsTestService{
@Override
publicStringgetError(@RequestParam("id")Integerid){
return"";
}
@Override
publicStringget1(){
returnnull;
}
@Override
publicStringget2(Stringparam){
returnnull;
}
@Override
publicFeignDemopost1(FeignDemodemo){
returnnull;
}
}
}

二、怎么切换 Client

Feign 中自带的是 HttpURLConnection,这个 client 健壮性差,可替换为老练的 Apache HttpClient 或 OkHttp 来进行网络恳求。

2.1 运用 Apache 的 HTTP Client

运用 Apache 的httpclient替换 Feign 中默认的 client。

2.1.1 添加依靠

<!--httpclient的依靠,因为选择了运用httpclient-->
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
</dependency>
<dependency>
<groupId>io.github.openfeign</groupId>
<artifactId>feign-httpclient</artifactId>
<version>10.4.0</version>
</dependency>

2.1.2 装备启用

装备中添加如下信息,表示启用httpclient

feign:
httpclient:
enabled:true

2.2 运用 OkHttp

2.2.1 添加依靠

在 Feign 中运用OkHttp作为网络恳求结构,则只需要在 pom 文件中加上feign-okhttp的依靠,代码如下:

<dependency>
<groupId>io.github.openfeign</groupId>
<artifactId>feign-okhttp</artifactId>
<version>10.2.0</version>
</dependency>

2.2.2 装备启用

feign:
okhttp:
enabled:true

三、怎么修正日志等级

在发送和接收恳求的时候,其内部将日志的打印输出定义成了四个等级,对应的概况如下:

等级 阐明
NONE 不做任何记载
BASIC 仅记载恳求办法和 URL 以及呼应状态代码和履行时间
HEADERS 记载基本信息以及恳求和呼应标头
FULL 记载恳求和呼应的标题,正文和元数据

3.1 经过装备文件修正日志等级

注意需要指定接口的全限定名

logging:
level:
com.zto.titans.test.feign.service.TestService:DEBUG

3.2 经过装备类修正日志等级

@Configuration
publicclassFooConfiguration{
@Bean
Logger.LevelfeignLoggerLevel(){
returnLogger.Level.FULL;
}
}

这个一看即懂,不再废话。

四、怎么实现数据紧缩

能够分别对 HTTP 通讯的requestresponse设置是否启用 GZIP 紧缩,装备办法如下:

feign:
compression:
request:
enabled:true
mime-types:text/xml,application/xml,application/json#装备紧缩支撑的MIMETYPE
min-request-size:2048#装备紧缩数据大小的下限
response:
enabled:true#装备呼应GZIP紧缩

五、FeignClient 的装备以及装备的优先级机制

有 2 种途径设置 FeignClient 的装备,经过自定义装备类来设置装备和在装备文件中设置,其间装备文件方法有点特别,它里边能够指定大局装备对一切 FeignClient 有用,也能够为特定名称的 FeignClient 设置专属的装备。

5.1 经过自定义装备类来定制装备

实现一个装备类

publicclassTestConfiguration{
@Bean
Logger.LevelfeignLoggerLevel(){
returnLogger.Level.FULL;
}
}

将装备类TestConfiguration指定给configuration

@FeignClient(
name="test-service",
configuration={FeignInterceptor2.class,TestConfiguration.class}
)

5.2 在装备文件中设置大局装备

feign.client.config.default.xxx ,这个default意为大局的装备属性。

feign:
client:
config:
default:
connectTimeout:5000
readTimeout:5000
loggerLevel:basic

5.3 在装备文件中设置专属装备

feign.client.config.feignName.xxx , 给姓名为feignNameFeignClient指定专属的装备。

feign:
client:
config:
feignName:
connectTimeout:5000
readTimeout:5000
loggerLevel:full
errorDecoder:com.example.SimpleErrorDecoder
retryer:com.example.SimpleRetryer
requestInterceptors:
-com.example.FooRequestInterceptor
-com.example.BarRequestInterceptor
decode404:false
encoder:com.example.SimpleEncoder
decoder:com.example.SimpleDecoder

5.4 理解装备的优先级与拦截器的追加准则

org.springframework.cloud.openfeign.FeignClientFactoryBean#configureFeign中能够确认以上 3 种装备的优先级:

configureUsingConfiguration(context,builder);//1
configureUsingProperties(properties.getConfig().get(properties.getDefaultConfig()),builder);//2
configureUsingProperties(properties.getConfig().get(this.contextId),builder);//3
  1. 第 1 类为经过自定义装备类来指定装备
  2. 第 2 类为在装备文件中的feign.client.config.default.xxx设置大局装备
  3. 第 3 类为在装备文件中的feign.client.config.feignName.xxx设置专属装备

5.4.1 优先级的作用

装备文件里的专属装备-掩盖->装备文件里的大局装备-掩盖->装备类的装备

5.4.2 追加的准则

RequestInterceptor是拦截器,能够在发送前做一些处理,比方一致添加header信息。每一类中的requestInterceptors能够存储多个拦截器,拦截器并非掩盖的作用,而是链式追加的作用;从履行顺序来看优先级是:1 > 2 > 3,即先履行装备类中指定的拦截器,然后是装备文件中指定的大局拦截器,最后是装备文件中指定的专属拦截器

需特别注意:RequestInterceptor的实现类(例如 RI-A,RI-B)上假如添加了@Component注解,就都会被扫描识别到,并被追加到第一类的requestInterceptors列表中;倘若不小心 RI-A 还在第 2 类中又被指定了,则还会将拦截器 RI-A 追加在第二类的requestInterceptors列表中,结果是会 RI-A 总计会履行 2 次;若也在第三类中指定 RI-A,则 RI-A 也在其列表中追加,结果是 RI-A 总计会履行 3 次。

5.4.3 拦截器的作用验证

以一个实例来验证阐明作用

  • 自定义三个 RequestInterceptor
classFeignInterceptorimplementsRequestInterceptor{
@Override
publicvoidapply(RequestTemplaterequestTemplate){
requestTemplate.header("user","myuser1");
requestTemplate.header("password","mypassword");
}
}
classFeignInterceptor1implementsRequestInterceptor{
@Override
publicvoidapply(RequestTemplaterequestTemplate){
requestTemplate.header("user1","myuser1");
requestTemplate.header("password1","mypassword1");
}
}
classFeignInterceptor2implementsRequestInterceptor{
@Override
publicvoidapply(RequestTemplaterequestTemplate){
requestTemplate.header("user2","myuser2");
requestTemplate.header("password2","mypassword2");
}
}
  • @FeignClient 中指定一个
@FeignClient(
name="test-service",
url="http://localhost:8080/feign/server/",
configuration={FeignInterceptor.class,TestConfiguration.class},
fallback=TestService.DefaultFallback.class
)
  • 装备中指定 2 个

default指定了一个,test-service里指定一个

feign:
httpclient:
enabled:true
okhttp:
enabled:true
client:
config:
default:
connectTimeout:5000
readTimeout:5000
#loggerLevel:none
requestInterceptors:
-com.zto.titans.test.feign.service.FeignInterceptor1
test-service:
#loggerLevel:basic
requestInterceptors:
-com.zto.titans.test.feign.service.FeignInterceptor2
logging:
level:
com.zto.titans.test.feign.service.TestService:DEBUG

依据追加逻辑,终究履行的顺序是:

  1. FeignInterceptor
  2. FeignInterceptor1
  3. FeignInterceptor2

总结

本篇首要介绍 SpringBoot 中要玩转 Feign 需要把握的如添加 pom 依靠、客户端注解启用、切换底层 HttpClient、装备数据紧缩、调整日志等级、定制装备、装备的优先级机制、添加拦截器以及拦截器的追加机制等常识,以实例 + 作用的方法帮读者高效全面并深化的理解它们。

最后说一句(请重视,莫错过)

假如这篇文章对您有协助,或者有所启发的话,欢迎重视公众号【 架构染色 】进行沟通和学习。您的支撑是我坚持写作最大的动力。

求一键三连:重视、点赞、转发。