撸了一个 Feign 增强包

简介: 最近准备将公司的一个核心业务系统用 Java 进行重构,大半年没写 Java ,JDK 都更新到 14 了,考虑到稳定性等问题最终还是选择的 JDK11。在整体架构选型时,由于是一个全新的系统,所以没有历史包袱,同时团队中也有多位大牛坐镇,因此我们的选项便大胆起来。最终结果就是直接一把梭,直接上未来的大趋势:Service Mesh,直接把什么 SpringCloud、Dubbo 这类分布式框架全部干掉。本次的重点不是讨论 Service Mesh 是什么、能解决什么问题、为什么选择它,毕竟我也在学习阶段,啥时候整明白线上也稳定了再和大家来交流。

问题


既然方向定了就开始实际撸码了,不过刚一开始就验证了”理想很丰满、现实很骨感“;


由于我们去掉了 SpringCloudDubbo 这类框架,服务的注册、发现、负载均衡等需求全部都下沉到 Service Mesh 中提供了。


但对于开发来说依然希望可以调用本地方法的方式来调用远程服务,这在 SpringCloud 这类框架中是很容易实现的,框架本身就有很好的支持。


回到我们这个场景,需求其实很简单,就是想达到 SpringCloud 中的 Feign 这样的声明式+注解的方式调用。


@Autowired
    private StoreClient client ;
    Store store = client.update(1, store)


使用 spring-cloud-openfeign 这个包其实就能实现上述的需求了,但这样会引入一些我们根本不会使用的 SpringCloud 的相关依赖,让人感觉”不干净了“;同时也和 Service Mesh 的理念相反,其中的一大目的就是要降低这类框架的侵入性。


其实 spring-cloud-openfeign 的核心就是 Feign,本身它也是可以开箱即用的,所以便尝试看 Feign 自己是否支持这样的用法。



通过官方文档可以得知:是可以定义接口的形式来调用远程接口的,但它本质上是不依赖其他库便可以使用,所以它本身是没有和 Spring 整合也是合情合理,但也就造成了没有现成库可供我们使用。


我们自然是不想写上图红框处的代码的,希望所有接口直接注入就可以使用。


使用


因此结合以上的需求便有了这个库 feign-plus

它的使用流程其实就是翻版的 spring-cloud-openfeign


@FeignPlusClient(name = "github", url = "${github.url}")
public interface Github {
    @RequestLine("GET /repos/{owner}/{repo}/contributors")
    List<GitHubRes> contributors(@Param("owner") String owner, @Param("repo") String repo);
}


SpringBoot 入口进行扫描:


@SpringBootApplication
@EnableFeignPlusClients(basePackages = "top.crossoverjie.feign.test")
public class DemoApplication {
  public static void main(String[] args) {
    SpringApplication.run(DemoApplication.class, args);
  }
}


Spring 上下文中直接注入使用:


@Autowired
    private Github github ;
    List<GitHubRes> contributors = github.contributors("crossoverJie", "feign-plus");
    logger.info("contributors={}", new Gson().toJson(contributors));    


所以当我们需要调用一些外部第三方接口时(比如支付宝、外部 OpenAPI)便可类似于这样定义一个接口,把所有 HTTP 请求的细节屏蔽掉。


当然也适合公司内部之间的服务调用,和咱们以前写 SpringCloudDubbo 时类似;服务提供方提供一个 Client 包,消费方直接依赖便可以调用。其他的负载均衡、容错之类的由 Service Mesh 替我们完成。


对于内部接口,也可以加上 @RequestMapping("/path") 注解:



在请求时便会在 url 后拼接上 /order,这样在配置 feign.order.service.url 时只需要填入服务提供方的域名或 IP 即可。


feign-plus 也支持切换具体的 httpclient,默认是 okhttp3,通过以下配置便可更改。


# default(okhttp3)
feign.httpclient=http2Client


当然也有其他相关配置:


feign.plus.max-idle-connections = 520
feign.plus.connect-timeout = 11000
feign.plus.read-timeout = 12000


实现


最后简单聊聊是如何完成的吧,其实本质上就是 spring-cloud-openfeign 的浓缩版。


其中最为核心的便是

top.crossoverjie.feign.plus.factory.FeignPlusBeanFactory 类。



该类实现了 org.springframework.beans.factory.FactoryBean接口,并重写了 getObject() 方法返回一个对象。


这段代码是不是似曾相识,其实就是 Feign 的官方 demo


这里所返回的对象其实就是我们定义的接口的代理对象,而这个对象本身则是 Feign ,所以再往里说:我们的 http 请求编解码、发起请求等逻辑又被这个 feign 对象所代理了。



这个 HardCodedTarget 则是 Feign 内部用于代理最终请求的对象。


有一个小难受的地方:这样的自己定义 Bean 然后注入对象 Idea 是识别不了的,认为当前上下文没有该 Bean,但是 spring-cloud-openfeign 却可以识别。


由于 Feign 支持多个客户端,所以这里的客户端可以通过配置文件动态指定。



利用 SpringBoot 提供的 @ConditionalOnExpression 注解可以根据配置动态的选择使用哪个 httpclient,也就是动态选择生成哪个 Bean


总结


这个库的逻辑非常简单,本质上就是封装了 Feign 并提供了 SpringBoot 的支持,欢迎有类似需求的朋友下载使用。


feign-plus源码:github.com/crossoverJi…


相关文章
|
28天前
|
Java Kotlin 索引
学习Spring框架特性及jiar包下载
Spring 5作为最新版本,更新了JDK基线至8,修订了核心框架,增强了反射和接口功能,支持响应式编程及Kotlin语言,引入了函数式Web框架,并提升了测试功能。Spring框架可在其官网下载,包括文档、jar包和XML Schema文档,适用于Java SE和Java EE项目。
31 0
|
3月前
|
算法 Java
Java项目不使用框架如何实现限流?
Java项目不使用框架如何实现限流?
40 2
|
4月前
|
前端开发 Java API
一文教会你如何简单使用Fegin进行远程服务调用
这篇文章介绍了如何在分布式微服务架构中使用Feign进行远程服务调用,包括Feign的基本介绍、使用步骤,以及在项目中的实际运用方法,并通过测试验证了调用远程服务的成功性。
一文教会你如何简单使用Fegin进行远程服务调用
|
7月前
|
JSON Java 关系型数据库
【Feign】 基于 Feign 远程调用、 自定义配置、性能优化、实现 Feign 最佳实践
【Feign】 基于 Feign 远程调用、 自定义配置、性能优化、实现 Feign 最佳实践
275 0
|
7月前
【十九】搭建SpringCloud项目三(Feign)
【十九】搭建SpringCloud项目三(Feign)
60 0
|
缓存 负载均衡 监控
【SpringCloud】Eureka 案例上手稍微带点原理(2)
2. Eureka 2.1 Eureka 概述 Eureka 是 Netflix 提供的基于 REST 的服务发现组件,用于帮助开发者管理微服务架构中的服务实例。它提供了一个可伸缩的注册中心,可以让每个微服务都能够找到其他微服务的位置和元数据信息,并对其进行负载均衡、自动故障转移等操作。
|
前端开发 Java 开发者
正式抛弃 Feign!Spring 6 推出新特性:HTTP Interface,这波太秀了!
正式抛弃 Feign!Spring 6 推出新特性:HTTP Interface,这波太秀了!
106 0
正式抛弃 Feign!Spring 6 推出新特性:HTTP Interface,这波太秀了!
|
JSON 负载均衡 Java
基于Feign远程调用、自定义Feign配置、性能优化及最佳实践
基于Feign远程调用、自定义Feign配置、性能优化及最佳实践
968 0
|
JSON 编解码 安全
Feign实战技巧篇
Feign实战技巧篇
140 0
|
消息中间件 缓存 JavaScript
这16个有用的 SpringBoot 扩展接口,居然还有人不知道?
这16个有用的 SpringBoot 扩展接口,居然还有人不知道?