@FeignClient注解中的contextId属性
在使用@FeignClient注解前,我们需要先引入其相关依赖,版本为3.0.1
1
2
3
4
5
|
< dependency > < groupId >org.springframework.cloud</ groupId > < artifactId >spring-cloud-starter-openfeign</ artifactId > < version >3.0.1</ version > </ dependency > |
例如我们有一个user服务,user服务中有很多个接口,我们通过@FeignClient来实现接口的调用,不想将所有的调用接口都定义在一个接口类中,因此构建了下述两个Feign接口类:
1
2
3
4
5
6
7
8
9
10
|
@FeignClient (name = "user-server" ) public interface UserServerClient1 { @GetMapping ( "/user/get" ) public User getUser( @RequestParam ( "id" ) int id); } @FeignClient (name = "user-server" ) public interface UserServerClient2 { @GetMapping ( "/user/getAll" ) public List<User> getAllUser(); } |
这种情况下启动项目,项目就会报错,因为Bean的名称冲突了,具体错误如下:
Description:
The bean 'user-server.FeignClientSpecification' could not be registered. A bean with that name has already been defined and overriding is disabled.
Action:
Consider renaming one of the beans or enabling overriding by setting spring.main.allow-bean-definition-overriding=true
解决方法一
在yml配置文件中新增下述配置,允许出现beanName一样的BeanDefinition
1
2
3
|
spring: main: allow-bean-definition-overriding: true |
解决方法二
为每个FeignClient手动指定不同的contextId,contextId的作用是用来区分FeignClient实例
1
2
3
4
5
6
7
8
9
10
|
@FeignClient (contextId = "userService1" ,name = "user-server" ) public interface UserServerClient1 { @GetMapping ( "/user/get" ) public User getUser( @RequestParam ( "id" ) int id); } @FeignClient (contextId = "userService1" ,name = "user-server" ) public interface UserServerClient2 { @GetMapping ( "/user/getAll" ) public List<User> getAllUser(); } |
FeignClient注解及参数问题
在用分布式架构SpringBoot的SpringCloud技术开发过程中,@FeignClient 是一个常用的注解,且很重要的功能。它是Feign客户端提供负载均衡的热插拔注解,通过该注解可以动态代理创建Feign客户端。
简单理解就是,分布式架构服务之间,各子模块系统内部通信的核心。
一般在一个系统调用另一个系统的接口时使用,如下:
注解
1
2
3
4
|
@FeignClient ( "XXX" ) public interface XX{ .... } |
该注解一般创建在 interface 接口中,然后在业务类@Autowired进去使用非常简单方便。
问题背景
创建好interface接口后,当然要把调用该服务的接口方法定义出来,该方法对应本FeignClient的controller接口,必须重写该接口方法(返回对象,参数值完全一样)。
启动项目出现如下报错时,咋一看以为是在业务类中调用该接口方法时,传参为空null而报错。
FactoryBean threw exception on object creation; nested exception is
java.lang.IllegalStateException: RequestParam.value() was empty on parameter 0
当把传参用数据代替时,重新启动时;任然报如上错误。
贴一个报错全截图
org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'withdrawCountRecordController': Unsatisfied dependency expressed through field 'withdrawCountService'; nested exception is org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'withdrawCountServiceImpl': Unsatisfied dependency expressed through field 'cumClient'; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'com.epaylinks.efps.pas.clr.client.CumClient': FactoryBean threw exception on object creation; nested exception is java.lang.IllegalStateException: RequestParam.value() was empty on parameter 0 at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:588) at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:88) at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:366) at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1264) at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:553) at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:483) at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:306) at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230) at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:302) at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:197)
解决办法
在@FeignClien("XX") 接口类中,检查每个方法的参数定义时:
是否有如下情形
1
2
3
4
|
@RequestMapping (value= "/XXX/query" , method = RequestMethod.GET) public PageResult<XXutionResp> query( @RequestParam (required = false ) String XXCode, @RequestParam (value = "XXnName" ,required = false ) String institutionName, @RequestParam (value = "startTime" ,required = false ) String startTime, |
问题就在这里:
1
|
@RequestParam (required = false ) String XXCode |
这个参数少了个value = "XXCode", 这个是Spring 4.0版本后,@RequestParam 注解对参数传值有了很好的封装特性并严格校验。
改为:
1
|
@RequestParam (value = "XXCode" , required = false ) String XXCode |
之后,问题完美解决;重启项目正常。
另外,插一句:当在项目多个地方调用同一个@FeignClien("XX")某项目时,在多个包中创建接口,并无影响。
以上为个人经验,希望能给大家一个参考,也希望大家多多支持服务器之家。
原文链接:https://blog.csdn.net/y_bccl27/article/details/120034118