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";
}
}
}
