feign攔截器和解碼器


原文鏈接:https://blog.csdn.net/xuguofeng2016/article/details/107882619

業務需求

在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要高。

這個類的核心代碼如下:

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

Feign請求攔截器

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

示例如下:

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

MyClientInterceptor類:

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

Feign解碼器

解碼器概述

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

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

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

繼承SpringDecoder自定義解碼器

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

注入自定義解碼器

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

@Slf4j @Configuration @ConditionalOnClass({Feign.class}) @AutoConfigureBefore(FeignAutoConfiguration.class) public class CommonLogFeignConfig { @Autowired private ObjectFactory<HttpMessageConverters> messageConverters; @Bean public Decoder feignDecoder() { return new OptionalDecoder(new ResponseEntityDecoder(new TraceDecoder(this.messageConverters))); } }


免責聲明!

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



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