当前位置:网站首页>【微服务|openfeign】@FeignClient详解
【微服务|openfeign】@FeignClient详解
2022-07-04 03:51:00 【步尔斯特】
文章目录
上一篇,我们通过使用sentinel整合feign,对二者都有了初步的了解,这一篇,更侧重于对feign的使用以及其细节。
整合的步骤大体和前者一致,我们先来看看@FeignClient。

value/name
value和name的作用一样,如果没有配置url那么配置的值将作为服务名称,用于服务发现。
反之只是一个名称。
如果同时指定了url和name/value , 以url为准, name/value将作为服务的名称,url为服务的地址。
serviceId
serviceId已经废弃了,直接使用name即可。
contextId
如果有两个feignclient的名称都一样,可以通过指定不同的contextId来区分,不然同时存在两个bean就报错了。
当然,也可以配置spring.main.allow-bean-definition-overriding=true,作用是允许出现beanName一样的BeanDefinition。
让我们看一看源码:
org.springframework.cloud.openfeign.FeignClientsRegistrar#getClientName
private String getClientName(Map<String, Object> client) {
if (client == null) {
return null;
}
String value = (String) client.get("contextId");
if (!StringUtils.hasText(value)) {
value = (String) client.get("value");
}
if (!StringUtils.hasText(value)) {
value = (String) client.get("name");
}
if (!StringUtils.hasText(value)) {
value = (String) client.get("serviceId");
}
if (StringUtils.hasText(value)) {
return value;
}
throw new IllegalStateException("Either 'name' or 'value' must be provided in @"
+ FeignClient.class.getSimpleName());
}
可以看到如果配置了contextId就会用contextId,如果没有配置就会去value然后是name最后是serviceId。默认都没有配置,当出现一个服务有多个Feign Client的时候就会报错了。
其次的作用是在注册FeignClient中,contextId会作为Client 别名的一部分,如果配置了qualifier优先用qualifier作为别名。
private void registerFeignClient(BeanDefinitionRegistry registry,
AnnotationMetadata annotationMetadata, Map<String, Object> attributes) {
String className = annotationMetadata.getClassName();
BeanDefinitionBuilder definition = BeanDefinitionBuilder
.genericBeanDefinition(FeignClientFactoryBean.class);
validate(attributes);
definition.addPropertyValue("url", getUrl(attributes));
definition.addPropertyValue("path", getPath(attributes));
String name = getName(attributes);
definition.addPropertyValue("name", name);
String contextId = getContextId(attributes);
definition.addPropertyValue("contextId", contextId);
definition.addPropertyValue("type", className);
definition.addPropertyValue("decode404", attributes.get("decode404"));
definition.addPropertyValue("fallback", attributes.get("fallback"));
definition.addPropertyValue("fallbackFactory", attributes.get("fallbackFactory"));
definition.setAutowireMode(AbstractBeanDefinition.AUTOWIRE_BY_TYPE);
String alias = contextId + "FeignClient";
AbstractBeanDefinition beanDefinition = definition.getBeanDefinition();
beanDefinition.setAttribute(FactoryBean.OBJECT_TYPE_ATTRIBUTE, className);
// has a default, won't be null
boolean primary = (Boolean) attributes.get("primary");
beanDefinition.setPrimary(primary);
String qualifier = getQualifier(attributes);
if (StringUtils.hasText(qualifier)) {
alias = qualifier;
}
BeanDefinitionHolder holder = new BeanDefinitionHolder(beanDefinition, className,
new String[] {
alias });
BeanDefinitionReaderUtils.registerBeanDefinition(holder, registry);
}
url
用于配置指定服务的地址,相当于直接请求这个服务,不经过负载均衡器的服务选择。
decode404
当调用请求发生404错误时,decode404的值为true,那么会执行decoder解码,否则抛出异常。
configuration
configuration是配置Feign配置类,在配置类中可以自定义Feign的Encoder、Decoder、LogLevel、Contract等。
fallback
定义容错的处理类,也就是回退逻辑,fallback的类必须实现Feign Client的接口,无法知道熔断的异常信息。
fallbackFactory
也是容错的处理,可以知道熔断的异常信息。
path
path定义当前FeignClient访问接口时的统一前缀,比如接口地址是/user/get, 如果你定义了前缀是user, 那么具体方法上的路径就只需要写/get 即可,当我们项目中配置了server.context-path,server.servlet-path时使用。
primary
primary对应的是@Primary注解,默认为true,官方这样设置也是有原因的。当我们的Feign实现了fallback后,也就意味着Feign Client有多个相同的Bean在Spring容器中,当我们在使用@Autowired进行注入的时候,不知道注入哪个,所以我们需要设置一个优先级高的,@Primary注解就是干这件事情的。
qualifier
qualifier对应的是@Qualifier注解,一般场景直接@Autowired直接注入就可以了。
如果我们的Feign Client有fallback实现,默认@FeignClient注解的primary=true, 意味着我们使用@Autowired注入是没有问题的,会优先注入你的Feign Client。
如果你鬼斧神差的把primary设置成false了,直接用@Autowired注入的地方就会报错,不知道要注入哪个对象。
解决方案很明显,你可以将primary设置成true即可,如果由于某些特殊原因,你必须得去掉primary=true的设置,这种情况下我们怎么进行注入,我们可以配置一个qualifier,然后使用@Qualifier注解进行注入。
边栏推荐
- [paddleseg source code reading] paddleseg calculates Miou
- Tcpclientdemo for TCP protocol interaction
- postgresql 用户不能自己创建表格配置
- 如何有效远程办公之我见 | 社区征文
- 【webrtc】m98 ninja 构建和编译指令
- 量子力学习题
- Katalon框架测试web(二十六)自动发邮件
- 新型数据中心,助力加快构建以数据为关键要素的数字经济
- Pytest multi process / multi thread execution test case
- 深入浅出对话系统——使用Transformer进行文本分类
猜你喜欢

02 specific implementation of LS command

Idea modify body color

Lnk2038 detected a mismatch of "runtimelibrary": the value "md_dynamicrelease" does not match the value "mdd_dynamicdebug" (in main.obj)

还原窗口位置的微妙之处

My opinion on how to effectively telecommute | community essay solicitation

透过JVM-SANDBOX源码,了解字节码增强技术原理

2022-07-03:数组里有0和1,一定要翻转一个区间,翻转:0变1,1变0。 请问翻转后可以使得1的个数最多是多少? 来自小红书。3.13笔试。

The difference between bagging and boosting in machine learning

Exercices de renforcement des déclarations SQL (MySQL 8.0 par exemple)

2021 RSC | Drug–target affinity prediction using graph neural network and contact maps
随机推荐
2021 RSC | Drug–target affinity prediction using graph neural network and contact maps
SQL語句加强練習(MySQL8.0為例)
MySQL one master multiple slaves + linear replication
Wechat official account web page authorization
透过JVM-SANDBOX源码,了解字节码增强技术原理
Objective-C description method and type method
Confession code collection, who says program apes don't understand romance
2022-07-03: there are 0 and 1 in the array. Be sure to flip an interval. Flip: 0 becomes 1, 1 becomes 0. What is the maximum number of 1 after turning? From little red book. 3.13 written examination.
Lnk2038 detected a mismatch of "runtimelibrary": the value "md_dynamicrelease" does not match the value "mdd_dynamicdebug" (in main.obj)
JS实现文字滚动 跑马灯效果
Sales management system of lightweight enterprises based on PHP
三年进账35.31亿,这个江西老表要IPO了
JDBC 进阶
CesiumJS 2022^ 源码解读[0] - 文章目录与源码工程结构
Reduce function under functools
Huawei cloud Kunpeng engineer training (Guangxi University)
01 qemu 启动编译好的镜像 VFS: Unable to mount root fs on unknown-block(0,0)
[paddleseg source code reading] paddleseg custom data class
Select sorting and bubble sorting template
Simple dialogue system -- text classification using transformer