Feign集成Hystric报错
Feign集成Hystric报错
问题:在feign上使用hystric时一直报错。
@FeignClient(name = "provider-server", fallback = ProviderClient.ProviderClientFallback.class)
@RequestMapping("/api/v1/provider")
public interface ProviderClient {
@GetMapping("/port")
String port();
class ProviderClientFallback implements ProviderClient {
@Override
public String port() {
return "provider error";
}
}
}
当时想OpenFeign会代理声明的接口生成实现类,再创建ProviderClientFallback,spring注入时不是会出问题吗...
猜测feign会自己加载 fallback = ProviderClient.ProviderClientFallback.class,创建时间,绑定fallback。可是。。。
Caused by: java.lang.IllegalStateException: No fallback instance of type class com.zuizui.cloud.feign.feign.ProviderClient$ProviderClientFallback found for feign client provider-server
于是查文档发现:
When using Feign with Hystrix fallbacks, there are multiple beans in the ApplicationContext of the same type. This will cause @Autowired to not work because there isn’t exactly one bean, or one marked as primary. To work around this, Spring Cloud Netflix marks all Feign instances as @Primary, so Spring Framework will know which bean to inject. In some cases, this may not be desirable. To turn off this behavior set the primary attribute of @FeignClient to false.
Spring Cloud Netflix将所有Feign实例标记为@Primary,因此Spring Framework将知道要注入哪个bean
@FeignClient(name = "hello", primary = false)
public interface HelloClient {
// methods here
}
所有默认注入的都是代理接口实例,不会是xxxfallback实例。除非指定primary = false
现在尝试将ProviderClientFallback实例化,加上@Component
@FeignClient(name = "provider-server", fallback = ProviderClient.ProviderClientFallback.class)
@RequestMapping("/api/v1/provider")
public interface ProviderClient {
@GetMapping("/port")
String port();
@Component
class ProviderClientFallback implements ProviderClient {
@Override
public String port() {
return "provider error";
}
}
}
产生新的问题:interface和url同时mapper到了同一个地址。
Caused by: java.lang.IllegalStateException: Ambiguous mapping. Cannot map 'com.zuizui.cloud.feign.feign.ProviderClient' method
public abstract java.lang.String com.zuizui.cloud.feign.feign.ProviderClient.port()
to {[/api/v1/provider/port],methods=[GET]}: There is already 'providerClient.ProviderClientFallback' bean method
public java.lang.String com.zuizui.cloud.feign.feign.ProviderClient$ProviderClientFallback.port() mapped
Url mapping 存在了继承关系。尝试将@RequestMapping("/api/v1/provider")放到方法声明上
@FeignClient(name = "provider-server", fallback = ProviderClient.ProviderClientFallback.class)
public interface ProviderClient {
@GetMapping("/api/v1/provider/port")
String port();
@Component
class ProviderClientFallback implements ProviderClient {
@Override
public String port() {
return "provider error";
}
}
}
启动成功。
(优雅)解决方法:2
可以注意到RequestMapping中的value是“/conputer/add”,一般我们在spring mvc中,前面一致的都会放在class上,但是如果把@RequestMapping(value = “/computer”)放在接口上的话,还是会报错。
进入FeignClient注解里看了下属性,有一个path属性,是用来表示接口内所有方法请求的前缀的,而不是像springmvc,在接口上配置前缀@RequestMapping
https://my.oschina.net/u/2000675/blog/2244769
修改代码
@FeignClient(name = "provider-server", fallback = ProviderClient.ProviderClientFallback.class, path="/api/v1/provider")
public interface ProviderClient {
@GetMapping("/port")
String port();
@Component
class ProviderClientFallback implements ProviderClient {
@Override
public String port() {
return "provider error";
}
}
}