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

    }
}
posted @ 2019-04-23 14:49  zuier~  阅读(1130)  评论(0编辑  收藏  举报