网站首页 > 教程文章 正文
一、什么是Feign?
Feign makes writing java http clients easier,这是官方给出的一个说明,本意翻译是:Feign使编写Java http客户端更容易,Feign是一个http请求调用的轻量级框架,可以以Java接口注解的方式调用Http请求,Feign可以通过处理注解,将请求模板化,当实际调用的时候,传入参数,根据参数再应用到请求上,进而转化成真正的请求。
Feign封装了Http调用流程,更适合面向接口化的编程习惯。
在服务调用的场景中,我们经常调用基于Http协议的服务,而我们经常使用到的远程调用框架可能有HttpURLConnection、Apache HttpComponnets、OkHttp3 、Forest、Netty等等,这些框架在基于自身的专注点提供了自身特性。而从角色划分上来看,他们的职能是一致的提供Http调用服务。
二、理解远程调用
- 本地调用(Local Procedure Call,简称LPC)
- 远程调用(Remote Procedure Call,简称RPC)
feign主要是为我们提供了远程调用的服务,那么什么是远程调用呢? 远程调用说白了可以理解为不同服务之间方法的调用,实质上是两台主机间的网络通信 ,涉及到网络通信又必然会有序列化、反序列化,编解码等一些必须要考虑的问题,现在业界内比较流行的一些 RPC 框架,例如:Dubbo提供的是基于接口的远程方法调用,通过rpc远程调用框架,客户端只需要知道接口的定义即可调用远程服务。
而 feign主要就是用来简化我们发起远程调用的代码,以一个远程调用Github开放的API为:
/**
* GitHub客户端GitHubFeign,访问GitHub开发平台API,开放平台API地址:https://www.apifox.cn/apihub/
*
* @author: jacklin
* @date: 2022/6/30 21:20
*/
@FeignClient(name = "github-client", url = "https://api.github.com")
public interface GitHubFeign {
/**
* 查找github标准库信息
* <p>
* https://api.github.com/search/repositories v
*
* @author: jacklin
* @since 2022/6/30 21:27
**/
@GetMapping(value = "/search/repositories", produces = MediaType.APPLICATION_JSON_VALUE)
String searchRepositories(@RequestParam("q") String q);
}
第一步: Maven pom文件中引入 OpenFeign 组件。
第二步:客户端需要定义一个GitHubFeign接口,里面定义一个searchRepositories()方法,可以看到这个接口上添加了@FeignClient注解,而括号里面指定了服务名:github-client,显示声明这个接口是用来远程调用GitHub API服务的,url用来指定调用服务的全路径,其他方法路径前缀必须与url地址一致,完整的请求路径URL地址:
https://api.github.com/search/repositories
第三步:需要在服务启动类添加@EnableFeignClients注解,在服务启动时,Spring扫描被@FeignClints修饰的接口,基于动态代理生成本地JDK Proxy代理对象实例,然后将这些代理实例注册到Spring IOC容器中,当远程接口被调用时,由Proxy代理实例去完成真正的远程访问,并返回结果。
第四步:在Controller引入GitHubFeign服务,完成远程服务调用:
@RestController
@RequestMapping(value = "/github", produces = MediaType.APPLICATION_JSON_VALUE)
public class GithubController {
@Resource
private GitHubFeign gitHubFeign;
/**
* 查找github标准库信息
*
* @author: jacklin
* @since 2022/6/30 21:36
**/
@GetMapping(value = "/searchRepositories")
String searchRepositories(@RequestParam(value = "q") String q) {
return gitHubFeign.searchRepositories(q);
}
}
返回结果数据如下:
可以看出,feign使得远程调用跟本地方法是一样,极大的简化了rpc远程调用的方式。
三、OpenFeign和Feign的区别
可以认为OpenFeign是Feign的增强版,不同的是OpenFeign支持Spring MVC注解
Feign | OpenFeign |
Feign是Netflix公司写的,是SpringCloud组件中的一个轻量级RESTful的HTTP服务客户端,是SpringCloud中的第一代负载均衡客户端。 | OpenFeign的前身是Neflix Feign,Spring Cloud在Feign的基础上扩展支持了SpringMVC的注解,如@RequestMapping等等。OpenFeign的@FeignClient可以解析SpringMVC的@RequestMapping注解下的接口,并通过动态代理的方式产生实现类,实现类中做负载均衡并调用其他服务。 |
OpenFeign和Feign底层都内置了Ribbon负载均衡组件,在导入OpenFeign依赖后无需专门导入Ribbon依赖,用做客户端负载均衡,去调用注册中心服务。
四、OpenFeign核心工作原理
1 通过 @EnableFeignCleints触发Spring应用程序对classpath中@FeignClient修饰类的扫描。
2 解析到 @FeignClient 修饰类后,Feign框架通过扩展Spring Bean Deifinition的注册逻辑,最终注册一个FeignClientFacotoryBean进入Spring容器
3 Spring容器在初始化其他用到 @FeignClient 接口的类时, 获得的是FeignClientFacotryBean产生的一个代理对象Proxy。
4 基于Java原生的动态代理机制,针对Proxy的调用,都会被统一转发给Feign框架所定义的一个 InvocationHandler,由该Handler完成后续的HTTP转换,发送、接收以及HTTP响应的工作。
五、OpenFeign包扫描原理
要想通过OpenFeign实现远程调用,就涉及到一个OpenFeign的核心注解:@EnableFeignClient,根据字面意思可以知道,该注解是开启OpenFeign的功能,一般都会被添加到我们的启动类上。
Spring包扫描的大体流程:
- 开启OpenFeign功能@EnableFeignClients,接着通过@Import(FeignClientsRegistrar.class) 这个import的方式导入FeignClientsRegistrar类,开启OpenFeign组件的加载。
@SpringBootApplication
@EnableFeignClients
public class MambaBlockDemoApplication {
public static void main(String[] args) {
SpringApplication.run(MambaBlockDemoApplication.class, args);
}
}
- FeignClientsRegistrar负责Feign接口的加载,源码如下:
@Override
public void registerBeanDefinitions(AnnotationMetadata metadata, BeanDefinitionRegistry registry) {
//注册配置
registerDefaultConfiguration(metadata, registry);
//注册FeignClient
registerFeignClients(metadata, registry);
}
- registerFeignClients()方法会调用findCandidateComponents()方法来查找指定路径的basePackages下所有被@FeignClients注解修饰的类、接口。
LinkedHashSet<BeanDefinition> candidateComponents = Set<BeanDefinition> findCandidateComponents(String basePackage)
- 只保留被@FeignClient的修饰的接口。
for (BeanDefinition candidateComponent : candidateComponents) {
if (candidateComponent instanceof AnnotatedBeanDefinition) {
// verify annotated class is an interface
AnnotatedBeanDefinition beanDefinition = (AnnotatedBeanDefinition) candidateComponent;
AnnotationMetadata annotationMetadata = beanDefinition.getMetadata();
Assert.isTrue(annotationMetadata.isInterface(), "@FeignClient can only be specified on an interface");
Map<String, Object> attributes = annotationMetadata
.getAnnotationAttributes(FeignClient.class.getCanonicalName());
String name = getClientName(attributes);
registerClientConfiguration(registry, name, attributes.get("configuration"));
//注入到Spring容器中
registerFeignClient(registry, annotationMetadata, attributes);
}
}
六、总结
本文通过远程调用的GitHub开放API用到的OpenFeign作为示例代码作为入口进行讲解。然后以图解+解读源码的方式深入剖析了OpenFeign的运行机制和架构设计。
作者:austin流川枫
链接:
https://juejin.cn/post/7116450470704463908
猜你喜欢
- 2025-09-11 Spring Boot3 中 RESTful 接口调用全解析:从阻塞到响应式的实战指南
- 2025-09-11 springcloud实战:服务间通信OpenFeign熔断
- 2025-09-11 项目终于用上了动态Feign,真香!_feign动态服务名
- 2025-09-11 RestTemplate和Feign的区别_feign和httpclient的区别
- 2025-09-11 OpenFeign:让你的Java代码像本地调用一样简单
- 2025-09-11 【完结14章】SpringCloud+Netty集群实战千万级 IM系统
- 2025-09-11 Eureka服务发现框架和微服务调用组件Feign
- 2025-09-11 「SpringCloud」(十二)OpenFeign+Ribbon实现负载均衡
- 2025-09-11 微服务 - 服务接口调用 OpenFeign
- 2025-09-11 Sentinel 限流详解-Sentinel与OpenFeign服务熔断那些事
- 最近发表
-
- K8s 部署频繁出错?一套流程教你快速定位故障,工作效率翻倍
- 防火墙服务无法启用,显示灰色的解决办法
- 网络问题-电脑无法上网处理思路以及办法 (总集)
- Win10学院:Windows Denfender无法启动怎么办?
- Windows账户登录问题解决方案_登录windows账户什么意思
- IIS无法启动提示计算机上"."的服务W3SVC,一分钟搞定,抓紧收藏
- 已申请到免费顶级域名如何管理_顶级域名免费注册
- 网站被劫持了老是跳转怎么办_网站被劫持到其它网站如何解决
- 这些“常用药”被注销!涉及维生素、去痛片、眼药水等!快看看你家有吗?
- 《皕宋楼藏书志》清 藏书家陆心源与其门人李宗莲合编的藏书目录
- 标签列表
-
- location.href (44)
- document.ready (36)
- git checkout -b (34)
- 跃点数 (35)
- 阿里云镜像地址 (33)
- qt qmessagebox (36)
- mybatis plus page (35)
- vue @scroll (38)
- 堆栈区别 (33)
- 什么是容器 (33)
- sha1 md5 (33)
- navicat导出数据 (34)
- 阿里云acp考试 (33)
- 阿里云 nacos (34)
- redhat官网下载镜像 (36)
- srs服务器 (33)
- pico开发者 (33)
- https的端口号 (34)
- vscode更改主题 (35)
- 阿里云资源池 (34)
- os.path.join (33)
- redis aof rdb 区别 (33)
- 302跳转 (33)
- http method (35)
- js array splice (33)