SpringCloud中@FeignClient注解中的contextId属性详解
⽬录
@FeignClient注解中的contextId属性
解决⽅法⼀
解决⽅法⼆
FeignClient注解及参数问题
问题背景
解决办法
@FeignClient注解中的contextId属性
在使⽤@FeignClient注解前,我们需要先引⼊其相关依赖,版本为3.0.1
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
<version>3.0.1</version>
</dependency>
例如我们有⼀个user服务,user服务中有很多个接⼝,我们通过@FeignClient来实现接⼝的调⽤,不想将所有的调⽤接⼝都定义在⼀个接⼝类中,因此构建了下述两个Feign接⼝类:
@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
spring:
main:
allow-bean-definition-overriding: true
解决⽅法⼆
为每个FeignClient⼿动指定不同的contextId,contextId的作⽤是⽤来区分FeignClient实例
@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客户端。
简单理解就是,分布式架构服务之间,各⼦模块系统内部通信的核⼼。
⼀般在⼀个系统调⽤另⼀个系统的接⼝时使⽤,如下:
注解
@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) atspringcloud和springboot
org.springframework.beans.factory.ateBean(AbstractAutowireCapableBeanFactory.java:483) at
org.springframework.beans.factory.support.Object(AbstractBeanFactory.java:306) at
org.springframework.beans.factory.Singleton(DefaultSingletonBeanRegistry.java:230) at
org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:302) at
org.springframework.beans.factory.Bean(AbstractBeanFactory.java:197)
解决办法
在@FeignClien("XX") 接⼝类中,检查每个⽅法的参数定义时:
是否有如下情形
@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,
问题就在这⾥:
@RequestParam(required = false) String XXCode
这个参数少了个value = "XXCode", 这个是Spring 4.0版本后,@RequestParam 注解对参数传值有了很好的封装特性并严格校验。
改为:
@RequestParam(value = "XXCode", required = false) String XXCode
之后,问题完美解决;重启项⽬正常。
另外,插⼀句:当在项⽬多个地⽅调⽤同⼀个@FeignClien("XX")某项⽬时,在多个包中创建接⼝,并⽆影响。
以上为个⼈经验,希望能给⼤家⼀个参考,也希望⼤家多多⽀持。
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论