比如我们有个user服务,但user服务中有很多个接口,我们不想将所有的调用接口都定义在一个FeignClient中,比如:
Client 1
@FeignClient(value = "cloud-user-service")
public interface RemoteUserClient {
@GetMapping("/user/get/v1")
public User getUser(@RequestParam("id") int id);
}
Client 2
@FeignClient(value = "cloud-user-service")
public interface RemoteUserClient2 {
@GetMapping("/user/get/v2")
public User getUser(@RequestParam("id") int id);
}
这种情况下启动就会报错了,因为Bean的名称冲突了,具体错误如下:
***************************
APPLICATION FAILED TO START
***************************
Description:
The bean 'cloud-user-servic.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
Process finished with exit code 0
这个错误已经提示了我们解决方法,去配置文件中添加如下配置即可,作用是允许出现beanName一样的BeanDefinition。
spring:
## 添加如下配置
main:
allow-bean-definition-overriding: true
另一种解决方案就是为每个Client手动指定不同的contextId,这样就不会冲突了。(推荐)
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
public @interface FeignClient {
/**
* This will be used as the bean name instead of name if present, but will not be used
* as a service id.
* 如果存在,它将用作bean名称,而不是名称,但不会用作服务id。
* @return bean name instead of name if present
*/
String contextId() default "";
}
为@FeignClient添加contextId属性
Client 1
@FeignClient(value = "cloud-user-service", contextId = "server1")
public interface RemoteUserClient {
@GetMapping("/user/get/v1")
public User getUser(@RequestParam("id") int id);
}
Client 2
@FeignClient(value = "cloud-user-service", contextId = "server2")
public interface RemoteUserClient2 {
@GetMapping("/user/get/v2")
public User getUser(@RequestParam("id") int id);
}
Spring Cloud OpenFeign 官方文档:https://cloud.spring.io/spring-cloud-openfeign/reference/html/#spring-cloud-feign-overriding-defaults
如果我们想创建多个具有相同名称或url的外部客户端,以便它们指向同一台服务器,但每个服务器都有不同的自定义配置,那么我们必须使用@FeignClient的contextId属性,以避免这些配置bean的名称冲突。