Feign攔截器和解碼器


 

一、業務需求

在Spring Cloud的項目中,A服務使用Feign調用B服務的某個接口,如果需要傳遞全局認證token或參數,在方法參數里面加相應字段的方式顯然是不可取的。

 

首先想到的是AOP方式,使用切面攔截Feign方法,在AOP切面里面向方法參數里面添加數據,Feign方法執行完成之后,從響應對象里面獲取返回的數據,這樣的方式可以解決數據的傳遞和接收,但也必將需要方法參數和響應對象的支持,與業務耦合,並不是合理的架構實現方案。

 

如果有某種機制可以攔截到Feign的請求對象和響應對象,便可以獲取到請求頭和響應頭,就可以使用請求頭和響應頭來傳遞數據。

 

經過一番調查,了解到Feign的RequestInterceptor可以攔截到Feign請求,可以獲取到請求對象和請求頭,但是RequestInterceptor無法處理響應。

 

於是又進行調查,得知解碼器Decoder是對響應進行解碼的組件,可以獲取到響應對象和響應頭。

 

在調查過程中,還有另外的收獲:FeignClientsConfiguration類。

 

二、FeignClientsConfiguration類

Feign默認配置類是FeignClientsConfiguration類,該類定義了Feign默認的編碼器、解碼器、所使用的契約等。

Spring Cloud允許通過注解@FeignClient的configuration屬性自定義Feign配置,自定義配置的優先級比FeignClientsConfiguration要高。

這個類的核心代碼如下:

 1 @Configuration
 2 public class FeignClientsConfiguration {
 3 
 4     @Autowired
 5     private ObjectFactory<HttpMessageConverters> messageConverters;
 6 
 7     @Autowired(required = false)
 8     private List<AnnotatedParameterProcessor> parameterProcessors = new ArrayList<>();
 9 
10     @Autowired(required = false)
11     private List<FeignFormatterRegistrar> feignFormatterRegistrars = new ArrayList<>();
12 
13     @Autowired(required = false)
14     private Logger logger;
15 
16     @Bean
17     @ConditionalOnMissingBean
18     public Decoder feignDecoder() {
19         return new OptionalDecoder(new ResponseEntityDecoder(new SpringDecoder(this.messageConverters)));
20     }
21 
22     @Bean
23     @ConditionalOnMissingBean
24     @ConditionalOnMissingClass("org.springframework.data.domain.Pageable")
25     public Encoder feignEncoder() {
26         return new SpringEncoder(this.messageConverters);
27     }
28 
29     @Bean
30     @ConditionalOnMissingBean
31     public Contract feignContract(ConversionService feignConversionService) {
32         return new SpringMvcContract(this.parameterProcessors, feignConversionService);
33     }
34 
35     @Bean
36     @Scope("prototype")
37     @ConditionalOnMissingBean
38     public Feign.Builder feignBuilder(Retryer retryer) {
39         return Feign.builder().retryer(retryer);
40     }
41 }

 

三、Feign請求攔截器

參考FeignClientsConfiguration類,我們可以編寫一個configuration類,注入自定義的RequestInterceptor實現類對象,在apply(RequestTemplate requestTemplate)方法中獲取到請求RestTemplate對象,使用RequestTemplate對象設置請求參數、添加請求頭。

示例如下:

1 @Configuration
2 public class MyConfig {
3     @Bean("myInterceptor")
4     public RequestInterceptor getRequestInterceptor() {
5         return new MyClientInterceptor();
6     }
7 }

 

MyClientInterceptor類:

1 class MyClientInterceptor implements RequestInterceptor {
2     @Override
3     public void apply(RequestTemplate requestTemplate) {
4         requestTemplate.query("name", "Allen");
5         requestTemplate
6               .header("token", "token")
7               .header("id", id);
8     }
9 }

 

四、Feign解碼器

1、解碼器概述

Feign解碼器負責對響應進行解碼,返回符合Feign接口需求的對象。

我們可以參考FeignClientsConfiguration類中的方式編寫和注入自定義的解碼器。

1 @Bean
2 @ConditionalOnMissingBean
3 public Decoder feignDecoder() {
4     return new OptionalDecoder(
5             new ResponseEntityDecoder(new SpringDecoder(this.messageConverters)));
6 }

 

2、繼承SpringDecoder自定義解碼器

 1 class TraceDecoder extends SpringDecoder {
 2 
 3     TraceDecoder(ObjectFactory<HttpMessageConverters> messageConverters) {
 4         super(messageConverters);
 5     }
 6 
 7     @Override
 8     public Object decode(Response response, Type type) throws IOException, FeignException {
 9 
10         // 這里可以從response對象里面獲取響應頭和響應體
11 
12         // 獲取響應頭
13         Map<String, Collection<String>> headers = response.headers();
14 
15         return super.decode(response, type);
16     }
17 }

 

3、注入自定義解碼器

feignDecoder()方法完全參考了FeignClientsConfiguration類的寫法。

 1 @Slf4j
 2 @Configuration
 3 @ConditionalOnClass({Feign.class})
 4 @AutoConfigureBefore(FeignAutoConfiguration.class)
 5 public class CommonLogFeignConfig {
 6 
 7     @Autowired
 8     private ObjectFactory<HttpMessageConverters> messageConverters;
 9 
10     @Bean
11     public Decoder feignDecoder() {
12         return new OptionalDecoder(new ResponseEntityDecoder(new TraceDecoder(this.messageConverters)));
13     }
14 }

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM