本文目錄
一、背景描述
在用分佈式架構SpringBoot的SpringCloud技術開發過程中,FeignClient 是一個常用的註解,且很重要的功能。
簡單理解就是,分佈式架構服務之間,各子模塊系統內部通信的核心。一般在一個系統調用另一個系統的接口時使用,註解如下:
@FeignClient(contextId = "hostControlClient", value = SystemConstant.APPLICATION_NAME)
public interface HostControlClient {
/**
* 主機重啓
* @param sn
* @return
*/
@PostMapping(value = "/host/reboot")
CommResponse hostReboot(@RequestParam("sn") String sn);
/**
* 修改主機oem
* @param sn
* @param oemFirm
* @return
*/
@PostMapping(value = "/host/updateOem")
CommResponse updateOemFirm(@RequestParam("sn") String sn, @RequestParam("sn") String oemFirm);
}
該註解一般創建在 interface 接口中,然後在業務類@Autowired 進去使用非常簡單方便。
二、錯誤信息
創建好interface接口後,當然要把調用該服務的接口方法定義出來,該方法對應着本FeignClient服務的controller接口,必須重寫該接口方法(返回對象,參數值完全一樣)。比如下面的Controller:
@Slf4j
@Api(value = "hostControlClient", tags = "下發主機api接口")
@RestController
public class HostControlClientController implements HostControlClient {
@Autowired
private HostControlService hostControlService;
// 以下是很多方法
}
但是啓動這個項目的時候,控制檯日誌報錯,完整錯誤信息如下:
org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'hostControlClientController': Unsatisfied dependency expressed through field 'hostControlClientService'; nested exception is org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'hostControlClientServiceImpl' defined in file [G:\****\2項目代碼\trunk\雲端\back-iot-operation(家居運營平臺)\back-iot-operation\iot-operation-business\target\classes\com\uiotsoft\back\iotoperation\business\service\impl\HostControlClientServiceImpl.class]: Unsatisfied dependency expressed through constructor parameter 0; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'com.uiotsoft.back.iotdevice.api.client.host.HostControlClient': FactoryBean threw exception on object creation; nested exception is java.lang.UnsupportedOperationException
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:596)
at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:90)
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessProperties(AutowiredAnnotationBeanPostProcessor.java:374)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1411)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:592)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:515)
at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:320)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:222)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:318)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:199)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:843)
at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:877)
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:549)
at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:142)
at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:775)
at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:397)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:316)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1260)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1248)
at com.uiotsoft.back.iotoperation.MainServer.main(MainServer.java:23)
Caused by: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'hostControlClientServiceImpl' defined in file [G:\****\2項目代碼\trunk\雲端\back-iot-operation(家居運營平臺)\back-iot-operation\iot-operation-business\target\classes\com\uiotsoft\back\iotoperation\business\service\impl\HostControlClientServiceImpl.class]: Unsatisfied dependency expressed through constructor parameter 0; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'com.uiotsoft.back.iotdevice.api.client.host.HostControlClient': FactoryBean threw exception on object creation; nested exception is java.lang.UnsupportedOperationException
at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:769)
at org.springframework.beans.factory.support.ConstructorResolver.autowireConstructor(ConstructorResolver.java:218)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.autowireConstructor(AbstractAutowireCapableBeanFactory.java:1341)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1187)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:555)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:515)
at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:320)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:222)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:318)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:199)
at org.springframework.beans.factory.config.DependencyDescriptor.resolveCandidate(DependencyDescriptor.java:277)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1248)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1168)
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:593)
... 19 common frames omitted
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'com.uiotsoft.back.iotdevice.api.client.host.HostControlClient': FactoryBean threw exception on object creation; nested exception is java.lang.UnsupportedOperationException
at org.springframework.beans.factory.support.FactoryBeanRegistrySupport.doGetObjectFromFactoryBean(FactoryBeanRegistrySupport.java:178)
at org.springframework.beans.factory.support.FactoryBeanRegistrySupport.getObjectFromFactoryBean(FactoryBeanRegistrySupport.java:101)
at org.springframework.beans.factory.support.AbstractBeanFactory.getObjectForBeanInstance(AbstractBeanFactory.java:1674)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.getObjectForBeanInstance(AbstractAutowireCapableBeanFactory.java:1249)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:257)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:199)
at org.springframework.beans.factory.config.DependencyDescriptor.resolveCandidate(DependencyDescriptor.java:277)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.addCandidateEntry(DefaultListableBeanFactory.java:1471)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.findAutowireCandidates(DefaultListableBeanFactory.java:1428)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1211)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1168)
at org.springframework.beans.factory.support.ConstructorResolver.resolveAutowiredArgument(ConstructorResolver.java:857)
at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:760)
... 32 common frames omitted
Caused by: java.lang.UnsupportedOperationException: null
at java.util.Collections$UnmodifiableCollection.add(Collections.java:1055)
at org.springframework.cloud.openfeign.support.FeignUtils.addTemplateParameter(FeignUtils.java:60)
at org.springframework.cloud.openfeign.support.SpringMvcContract$SimpleAnnotatedParameterContext.setTemplateParameter(SpringMvcContract.java:460)
at org.springframework.cloud.openfeign.annotation.RequestParamParameterProcessor.processArgument(RequestParamParameterProcessor.java:69)
at org.springframework.cloud.openfeign.support.SpringMvcContract.processAnnotationsOnParameter(SpringMvcContract.java:292)
at feign.Contract$BaseContract.parseAndValidateMetadata(Contract.java:110)
at org.springframework.cloud.openfeign.support.SpringMvcContract.parseAndValidateMetadata(SpringMvcContract.java:188)
at feign.Contract$BaseContract.parseAndValidatateMetadata(Contract.java:66)
at feign.hystrix.HystrixDelegatingContract.parseAndValidatateMetadata(HystrixDelegatingContract.java:46)
at feign.ReflectiveFeign$ParseHandlersByName.apply(ReflectiveFeign.java:154)
at feign.ReflectiveFeign.newInstance(ReflectiveFeign.java:52)
at feign.Feign$Builder.target(Feign.java:251)
at org.springframework.cloud.openfeign.HystrixTargeter.target(HystrixTargeter.java:55)
at org.springframework.cloud.openfeign.FeignClientFactoryBean.loadBalance(FeignClientFactoryBean.java:238)
at org.springframework.cloud.openfeign.FeignClientFactoryBean.getTarget(FeignClientFactoryBean.java:267)
at org.springframework.cloud.openfeign.FeignClientFactoryBean.getObject(FeignClientFactoryBean.java:247)
at org.springframework.beans.factory.support.FactoryBeanRegistrySupport.doGetObjectFromFactoryBean(FactoryBeanRegistrySupport.java:171)
... 44 common frames omitted
三、出錯原因
看上面一背景描述裏的代碼第二個方法 updateOemFirm()的參數定義時,@RequestParam兩個參數名字一樣,而在Spring 4.0版本後,@RequestParam 註解對參數傳值有了很好的封裝特性並嚴格校驗的原因,檢測到兩個參數名一樣,故導致這此報錯。
CommResponse updateOemFirm(@RequestParam("sn") String sn, @RequestParam("sn") String oemFirm);
四、解決方案
將上述的錯誤寫法修改爲:
CommResponse updateOemFirm(@RequestParam("sn") String sn, @RequestParam("oemFirm") String oemFirm);
項目重啓,問題得到完美解決。
拓展資料:那天晚上和@FeignClient註解的深度交流:https://www.jianshu.com/p/41aa8f8f6ad4