TIPS
本文基於Spring Cloud Finchley編寫,如需閱讀更新、更全的總結文章,詳見:
如何使用Feign構造多參數的請求
本文總結Feign常見問題及解決方案。
一、FeignClient接口如使用@PathVariable
,必須指定value屬性
代碼示例:
1
2
3
4
5
6
|
@FeignClient("microservice-provider-user")
public interface UserFeignClient {
@RequestMapping(value = "/simple/{id}", method = RequestMethod.GET)
public User findById(@PathVariable("id") Long id);
...
}
|
其中的@PathVariable("id")
中的”id”,也就是value屬性,必須指定,不能省略。
二、構造多參數請求
詳見:如何使用Feign構造多參數的請求
三、如需產生Hystrix Stream監控信息,需要做一些額外操作
Feign本身已經整合了Hystrix,可直接使用@FeignClient(value = "microservice-provider-user", fallback = XXX.class)
來指定fallback類,fallback類繼承@FeignClient所標註的接口即可。
但是假設如需使用Hystrix Stream進行監控,默認情況下,訪問http://IP:PORT/actuator/hystrix.stream
是會返回404,這是因爲Feign雖然整合了Hystrix,但並沒有整合Hystrix的監控。如何添加監控支持呢?需要以下幾步:
第一步:添加依賴,示例:
1
2
3
4
5
|
<!-- 整合hystrix,其實feign中自帶了hystrix,引入該依賴主要是爲了使用其中的hystrix-metrics-event-stream,用於dashboard -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-hystrix</artifactId>
</dependency>
|
第二步:在啓動類上添加@EnableCircuitBreaker
註解,示例:
1
2
3
4
5
6
7
8
9
|
@SpringBootApplication
@EnableFeignClients
@EnableDiscoveryClient
@EnableCircuitBreaker
public class MovieFeignHystrixApplication {
public static void main(String[] args) {
SpringApplication.run(MovieFeignHystrixApplication.class, args);
}
}
|
第三步:在application.yml中添加如下內容,暴露hystrix.stream端點:
1
2
3
4
5
|
management:
endpoints:
web:
exposure:
include: 'hystrix.stream'
|
這樣,訪問任意Feign Client接口的API後,再訪問http://IP:PORT/actuator/hystrix.stream
,就會展示一大堆Hystrix監控數據了。
四、Java代碼自定義Feign Client的注意點與坑
代碼示例:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
|
@FeignClient(name = "microservice-provider-user", configuration = UserFeignConfig.class)
public interface UserFeignClient {
@GetMapping("/users/{id}")
User findById(@PathVariable("id") Long id);
}
/**
* 該Feign Client的配置類,注意:
* 1. 該類可以獨立出去;
* 2. 該類上也可添加@Configuration聲明是一個配置類;
* 配置類上也可添加@Configuration註解,聲明這是一個配置類;
* 但此時千萬別將該放置在主應用程序上下文@ComponentScan所掃描的包中,
* 否則,該配置將會被所有Feign Client共享,無法實現細粒度配置!
* 個人建議:像我一樣,不加@Configuration註解
*
* @author zhouli
*/
class UserFeignConfig {
@Bean
public Logger.Level logger() {
return Logger.Level.FULL;
}
}
|
- 配置類上也可添加
@Configuraiton
註解,聲明這是一個配置類;但此時千萬別將該放置在主應用程序上下文@ComponentScan
所掃描的包中,否則,該配置將會被所有Feign Client共享(相當於變成了通用配置,其實本質還是Spring父子上下文掃描包重疊導致的問題),無法實現細粒度配置!
- 個人建議:像我一樣,不加@Configuration註解,省得進坑。
- 最佳實踐:儘量用配置屬性自定義Feign的配置!!!詳見:跟我學Spring Cloud(Finchley版)-10-Feign深入
五、首次請求失敗
詳見:Spring Cloud中,如何解決Feign/Ribbon第一次請求失敗的問題?
六、@FeignClient
註解屬性
1
|
@FeignClient(name = "microservice-provider-user")
|
在早期的Spring Cloud版本中,無需提供name屬性,從Brixton版開始,@FeignClient必須提供name屬性,否則應用將無法正常啓動!
另外,name、url等屬性支持佔位符。例如:
1
|
@FeignClient(name = "${feign.name}", url = "${feign.url}")
|
七、類級別的@RequestMapping會被Spring MVC加載
1
2
3
4
5
|
@RequestMapping("/users")
@FeignClient(name = "microservice-user")
public class TestFeignClient {
// ...
}
|
類上的@RequestMapping
註解也會被Spring MVC加載。該問題現已經被解決,早期的版本有兩種解決方案:
方案1:不在類上加@RequestMapping
註解;
方案2:添加如下代碼:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
|
@Configuration
@ConditionalOnClass({ Feign.class })
public class FeignMappingDefaultConfiguration {
@Bean
public WebMvcRegistrations feignWebRegistrations() {
return new WebMvcRegistrationsAdapter() {
@Override
public RequestMappingHandlerMapping getRequestMappingHandlerMapping() {
return new FeignFilterRequestMappingHandlerMapping();
}
};
}
private static class FeignFilterRequestMappingHandlerMapping extends RequestMappingHandlerMapping {
@Override
protected boolean isHandler(Class<?> beanType) {
return super.isHandler(beanType) && !beanType.isInterface();
}
}
}
|
相關Issue:https://github.com/spring-cloud/spring-cloud-netflix/issues/466