spring openfeign 自定义路径调用
算算时间竟有半年多没写博客了,其实这些时间也折腾了不少东西,比如体验了下 ChatGPT,把它接入到微信里做机器人,扩展研究了下逆向微信的消息收发,后面有空再写写相关内容吧,本次主要是记录下关于项目中openfeign
的自定义使用。
Spring Cloud OpenFeign 是什么?
Spring Cloud OpenFeign 是基于 Feign 的声明式 Web 服务客户端。它使编写 Web 服务客户端变得更加容易。Feign
本身的一些优秀的特性也被继承,如:
- 支持多种编解码方式, jackson, Gson 等
- 支持多种调用通讯端,如:Apache HTTP, OK HTTP 等
- 支持指标监控
- 日志,断路器等其他杂项功能
关于其使用比较简单,以下是一个官方的例子:
1 |
|
可以看到接口的定义方式类似 Spring MVC
,消除了具体的调用实现,显的更为清楚简洁。
遇到的问题
OpenFeign
的使用是简洁的,但并不是完美的,在使用中会遇到一个问题即:请求地址路径不固定,虽然可以通过 profile
机制在不同的场景下切换路径,但这种方式仍然无法实现路径的热更新。
着手解决
众所周知 Spring 是模式大师,经过其抽象定义,原本的使用方式就会被包装起来,所以要解决路径动态切换的问题可以从Feign
的使用中去倒推。
在Feign
使用中路径的切入比较简单,看看官方的例子
1 | Feign.builder().decoder(new GsonDecoder()).target(GitHub.class, "https://api.github.com"); |
其中的target
方法支持传入一个Target
类来修改运行时的参数,可以自定义Target
类类似如下
1 | class DynamicUrlTarget<T> implements Target<T> { |
那么倒推Spring OpenFeign
查询target
方法发现在DefaultTargeter
中有调用,该接口实现了Spring
的Targeter
接口,这也意味着可以进行自定义替换。这里先扩展Targeter
接口方法使其支持路径配置。
1 | public interface ApiCaller extends Targeter { |
在代码中还用到了WrapTarget
这个类,这个类主要用于处理参数配置替换等,相关代码如下
1 | public class WrapTarget<T> implements Target<T> { |
如上便完成了自定义路径的包装,但麻烦又来了,如何让 Spring 加载 ApiCaller
而非默认的DefaultTargeter
,这里就需要了解注解@FeignClient
是如何工作,整理了下流程大概如下
- 首先代码定义声明
@FeignClient
FeignClientsRegistrar
作为注解注册器做了扫描处理, 核心方法registerBeanDefinitions
代码值得关注的有两部分代码registerClientConfiguration
注册注解中的configuration
配置为FeignClientSpecification
BeanregisterFeignClient
注册注解为FeignClientFactoryBean
工厂 Bean
FeignAutoConfiguration
中将自定义的FeignClientSpecification
注入到FeignContext
Bean- 在实际构建代理类时利用
FeignContext
及相关的FeignClientSpecification
最终构建出Feign
对象
而根据最后一步构建Feign
实例的代码中 Targeter targeter = get(context, Targeter.class);
可以和之前自定义的ApiCaller
衔接起来。
简单的一个示例如下
1 | class DynamicUrlApiCaller implements ApiCaller { |
接着将类DynamicUrlApiCaller
配置在@FeignClient
的configuration
处,类似如下
1 |
|
不用担心dao
的注入问题,实际上configuration
在处理中会自动实例化出一个继承父容器的子容器,所以在实例化中不用担心依赖注入问题大胆使用即可。
写在最后
关于动态路径的切换还是有一定场景的,但是搜遍网上的教程却很少有可以借鉴参考的,这个时候就要动用自己的改造能力站在巨人的肩膀上作出微创新,希望这篇文章能帮到你。