Spring Cloud 中@FeignClient注解中的contextId屬性詳解
@FeignClient注解中的contextId屬性
在使用@FeignClient注解前,我們需要先引入其相關(guān)依賴,版本為3.0.1
<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-openfeign</artifactId> <version>3.0.1</version> </dependency>
例如我們有一個(gè)user服務(wù),user服務(wù)中有很多個(gè)接口,我們通過@FeignClient來實(shí)現(xiàn)接口的調(diào)用,不想將所有的調(diào)用接口都定義在一個(gè)接口類中,因此構(gòu)建了下述兩個(gè)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(); }
這種情況下啟動(dòng)項(xiàng)目,項(xiàng)目就會(huì)報(bào)錯(cuò),因?yàn)锽ean的名稱沖突了,具體錯(cuò)誤如下:
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配置文件中新增下述配置,允許出現(xiàn)beanName一樣的BeanDefinition
spring: main: allow-bean-definition-overriding: true
解決方法二
為每個(gè)FeignClient手動(dòng)指定不同的contextId,contextId的作用是用來區(qū)分FeignClient實(shí)例
@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注解及參數(shù)問題
在用分布式架構(gòu)SpringBoot的SpringCloud技術(shù)開發(fā)過程中,@FeignClient 是一個(gè)常用的注解,且很重要的功能。它是Feign客戶端提供負(fù)載均衡的熱插拔注解,通過該注解可以動(dòng)態(tài)代理創(chuàng)建Feign客戶端。
簡單理解就是,分布式架構(gòu)服務(wù)之間,各子模塊系統(tǒng)內(nèi)部通信的核心。
一般在一個(gè)系統(tǒng)調(diào)用另一個(gè)系統(tǒng)的接口時(shí)使用,如下:
注解
@FeignClient("XXX") public interface XX{ .... }
該注解一般創(chuàng)建在 interface 接口中,然后在業(yè)務(wù)類@Autowired進(jìn)去使用非常簡單方便。
問題背景
創(chuàng)建好interface接口后,當(dāng)然要把調(diào)用該服務(wù)的接口方法定義出來,該方法對(duì)應(yīng)本FeignClient的controller接口,必須重寫該接口方法(返回對(duì)象,參數(shù)值完全一樣)。
啟動(dòng)項(xiàng)目出現(xiàn)如下報(bào)錯(cuò)時(shí),咋一看以為是在業(yè)務(wù)類中調(diào)用該接口方法時(shí),傳參為空null而報(bào)錯(cuò)。
FactoryBean threw exception on object creation; nested exception is
java.lang.IllegalStateException: RequestParam.value() was empty on parameter 0
當(dāng)把傳參用數(shù)據(jù)代替時(shí),重新啟動(dòng)時(shí);任然報(bào)如上錯(cuò)誤。
貼一個(gè)報(bào)錯(cuò)全截圖
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") 接口類中,檢查每個(gè)方法的參數(shù)定義時(shí):
是否有如下情形
@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
這個(gè)參數(shù)少了個(gè)value = "XXCode", 這個(gè)是Spring 4.0版本后,@RequestParam 注解對(duì)參數(shù)傳值有了很好的封裝特性并嚴(yán)格校驗(yàn)。
改為:
@RequestParam(value = "XXCode", required = false) String XXCode
之后,問題完美解決;重啟項(xiàng)目正常。
另外,插一句:當(dāng)在項(xiàng)目多個(gè)地方調(diào)用同一個(gè)@FeignClien("XX")某項(xiàng)目時(shí),在多個(gè)包中創(chuàng)建接口,并無影響。
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
Spring Boot 整合單機(jī)websocket的步驟 附github源碼
websocket 是一個(gè)通信協(xié)議,通過單個(gè) TCP 連接提供全雙工通信,這篇文章主要介紹了Spring Boot 整合單機(jī)websocket的步驟(附github源碼),需要的朋友可以參考下2021-10-10Java發(fā)送https請(qǐng)求代碼實(shí)例
這篇文章主要介紹了Java發(fā)送https請(qǐng)求代碼實(shí)例,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2019-08-08如何使用Idea中的 Deployment 實(shí)現(xiàn)打包自動(dòng)部署
這篇文章主要介紹了使用Idea中的 Deployment 實(shí)現(xiàn)打包自動(dòng)部署,本文通過圖文并茂的形式給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2023-08-08性能爆棚的實(shí)體轉(zhuǎn)換復(fù)制工具M(jìn)apStruct使用詳解
這篇文章主要為大家介紹了性能爆棚的實(shí)體轉(zhuǎn)換復(fù)制工具M(jìn)apStruct使用詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-03-03Java反射 JavaBean對(duì)象自動(dòng)生成插入,更新,刪除,查詢sql語句操作
這篇文章主要介紹了Java反射 JavaBean對(duì)象自動(dòng)生成插入,更新,刪除,查詢sql語句操作,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧2020-08-08Java 類型相互轉(zhuǎn)換byte[]類型,Blob類型詳細(xì)介紹
這篇文章主要介紹了Java 類型相互轉(zhuǎn)換byte[]類型,Blob類型的相關(guān)資料,需要的朋友可以參考下2016-10-10Java中使用正則表達(dá)式的一個(gè)簡單例子及常用正則分享
這篇文章主要介紹了Java中使用正則表達(dá)式的一個(gè)簡單例子及常用正則分享,本文用一個(gè)驗(yàn)證Email的例子講解JAVA中如何使用正則,并羅列了一些常用的正則表達(dá)式,需要的朋友可以參考下2015-06-06Spring boot中@Conditional和spring boot的自動(dòng)配置實(shí)例詳解
本文通過實(shí)例給大家介紹了Spring boot中@Conditional和spring boot的自動(dòng)配置,需要的朋友可以參考下2018-05-05