本文目录
一、背景描述
在用分布式架构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项目代码 runk云端ack-iot-operation(家居运营平台)ack-iot-operationiot-operation-business argetclassescomuiotsoftackiotoperationusinessserviceimplHostControlClientServiceImpl.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项目代码 runk云端ack-iot-operation(家居运营平台)ack-iot-operationiot-operation-business argetclassescomuiotsoftackiotoperationusinessserviceimplHostControlClientServiceImpl.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