微服务分布式架构基础与实战:基于Spring Boot + Spring Cloud
上QQ阅读APP看本书,新人免费读10天
设备和账号都新为新人

3.4 【实例】Feign的拦截器

3.4.1 实例背景

Feign的拦截器是在Client端进行编写的,Client端在调用Server端前,会在自身内部进行Feign拦截。通常拦截是为了在Request Header报文头内部增加token之类的信息,使Feign在调用前统一处理请求/请求头/请求体。

本实例继续修改3.3节中的cloud-admin-8084工程,通过实现Feign的拦截器保证每次Feign的调用都会被拦截函数进行拦截。

3.4.2 在cloud-admin-8084工程中增加拦截器

通过实现feign.RequestInterceptor接口,来实现Feign的拦截器。使用@Configuration注解将Feign的拦截器注册到Spring容器上。在编写Feign拦截器Interceptor拦截器实现类的过程中,需要重写并实现apply函数,编写完该函数后,每次Feign请求都会经过AdminInterceptor拦截器。

AdminInterceptor.java拦截器的实现代码如下。

RequestTemplate是请求模板,即非线程安全的模板模型,可任意修改,所以通过复杂构造函数进行实现,请求对象都通过请求模板进行实例化。请求模板是Feign拦截器最重要的部分,RequestTemplate的使用方法非常简单,直接使用其中的函数即可。

3.4.3 当前项目结构

如图3-20所示,增加Feign的拦截器只需要增加AdminInterceptor.java类即可,不需要增加其他内容。

3.4.4 运行结果

在调用请求时,先进入拦截器,然后通过LoadBalancer实例化Feign的负载均衡器,代码如下。

图3-20

客户端在实例化请求前,先进入拦截器,然后请求其他微服务,其后台日志如图3-21所示。

图3-21

3.4.5 实例易错点

1.HTTP编码格式错误

如果发生HTTP编码格式错误,控制台会输出错误信息如下。

此时需要在拦截器中添加header报文头,更改HTTP编码格式为

由于此处没有编辑器校验,所以容易写错,若写错,Feign进入拦截器更改HTTP编码格式传输到Server端的时候,发生Client端的调用错误。注意,Feign不接受get请求进行实体类POJO作为参数传递,解决方案如下。

(1)将POJO转换成Map进行传递。

(2)将POJO拆分成多个参数再进行传递。

(3)入参以@ModelAttribute注解修饰,被@ModelAttribute注解修饰后,POJO会作为字符串拼接在URL上。但如果将POJO拆分成多个参数,URL过长可能会影响性能。

若在通常情况下Server服务提供方和Feign Client调用方的入参、出参等函数完全相同,则不会出现较多问题,代码如下。

2.Feign拦截器需注册到Spring容器中

如果没有将Feign拦截器作为Bean注册到Spring容器中,相当于没有自定义拦截器,不会发生其他任何异常。若没有注册到Spring容器中,可用编程的方式实例化FeignClient,伪代码如下。

通过代码构造了Feign的Client端,构造时已经将拦截器作为构造参数使用,因此不需要将Feign拦截器注册到Spring容器中。除上述方式外,将拦截器配置到application.yml资源配置文件中,也不需要将拦截器作为Bean注册到Spring容器中,配置代码如下。

此时需注意以下4点。

(1)feign.client.config.cloud-user.requestInterceptors中对应的数据相当于一个数组,可以多个叠加。

(2)“-”减号后有一个空格,“-”减号前比requestInterceptors节点前多两个空格。

(3)当前FeignClient的名字为cloud-user,上述配置是添加在cloud-admin-8084工程中的,但由于实例化的是cloud-user接口,所以FeignClient的名字为cloud-user。若拦截器较复杂,则推荐用资源配置的写法。如果要设置全局配置,可以将cloud-user改为default,即feign.client.config.default下为Feign拦截器的默认配置。

(4)不要将Feign拦截器注册到Spring容器中的同时,又在资源配置文件中进行配置,否则该场景下Feign会两次进入拦截器,输出日志如图3-22所示。

图3-22