不额外引入依赖,纯净的给 OpenFeign 添加上请求和响应拦截器
feign 它自带的拦截器 feign.RequestInterceptor
只能拦截请求, 做一些修改请求头、请求参数之类的动作。没办法将请求和响应一起拦截。
说实话,为什么feign只提供了一个这样子的残缺版钩子。 我也不是很懂。
这是feign自带的拦截器:
@Component public class FeignRequestInterceptor implements RequestInterceptor { @Override public void apply(RequestTemplate requestTemplate) { System.out.println(requestTemplate.path()); System.out.println(requestTemplate.url()); } }
如果想要加拦截器, 正常来说就只能新加依赖了, 比如换成okhttp, 然后在okhttp客户端上做文章。在添加响应拦截器这块网上搜到的东西也就只能给出这个解决方案了。
那么问题来了, 如果我就是不想换呢? 凭什么我只是想给他加个前后置的拦截器, 就要额外引入一个新的http客户端? 差不多得了。
所以我就不信了, 干脆直接断点进去看他源码吧,所以就随便跟了一下Spring Cloud OpenFeign的自动注入源码,发现还是可以比较轻松实现的。
那么这里我就给演示一下, 怎么操作。 这个方法就是: 自定义他的请求 Client。
首先需要看一下他是怎么自动注入的HTTP请求客户端。 因为他代码并不复杂, 所以发现和跟进的思路就不写了,这里直接将流程列出给大家看。
FeignClient的默认注入流程
1、spring.factories
org.springframework.cloud.openfeign.ribbon.FeignRibbonClientAutoConfiguration
–>
2、Spring Import
@Import(DefaultFeignLoadBalancedConfiguration.class)
–>
3、Spring auto configuration
@Configuration class DefaultFeignLoadBalancedConfiguration { @Bean @ConditionalOnMissingBean public Client feignClient(CachingSpringLoadBalancerFactory cachingFactory,SpringClientFactory clientFactory) { return new LoadBalancerFeignClient(new Client.Default(null, null), cachingFactory, clientFactory); } }
好, 那么这儿基本就是整个流程, 说白了基本就是使用Spring Boot 的 AutoCofiguration 机制 + Spring Import 机制导入了一个配置类。
这个配置类里就定义了Feign的客户端。
那么胜利的方程式就很明确了, 因为他加了 @ConditionalOnMissingBean
注解, 我们只要自己自定义一个Client交给Spring容器管理就行。
自定义Feign的Client
这里直接安排一个装饰器, 真实调用时还是用的默认的Client, 然后可以在其上自定义扩展。
代码如下所示:
public class TraceFeignClientDecorator implements Client { private final Client delegate; public TraceFeignClientDecorator(Client delegate) { this.delegate = delegate; } @Override public Response execute(Request request, Request.Options options) throws IOException { //do action.. Response response = delegate.execute(request, options); //do action.. return response; } }
然后像下面这样在Spring的配置类中注入自定义的Client就完成了
@Bean public Client feignClient(CachingSpringLoadBalancerFactory cachingFactory, SpringClientFactory clientFactory) { return new LoadBalancerFeignClient(new TraceFeignClientDecorator(new Client.Default(null, null)), cachingFactory, clientFactory); }
这样你所有的 FeignClient 接口, 实际走的就都是你自定义的HTTP客户端。
既然是你自定义的, 那么想做什么操作都是随意了, 这个代理逻辑实现还是很简单的,相信有点经验的都可以理解, 犯不着专门为了使OpenFeign可以拦截响应而去引入新的依赖了。
1 COMMENT