Feign調(diào)用中的兩種Header傳參方式小結(jié)
Feign調(diào)用中的兩種Header傳參方式
在Spring Cloud Netflix棧中,各個(gè)微服務(wù)都是以HTTP接口的形式暴露自身服務(wù)的,因此在調(diào)用遠(yuǎn)程服務(wù)時(shí)就必須使用HTTP客戶端。
我們可以使用JDK原生的URLConnection、Apache的Http Client、Netty的異步HTTP Client, Spring的RestTemplate。公司目前使用的是Feign。
下面來和大家一起學(xué)習(xí)下feign調(diào)用中兩種Header傳參方式。
在請(qǐng)求攔截器中統(tǒng)一配置
每次Feign調(diào)用中,需要傳遞一些安全校驗(yàn)參數(shù),比如說token,bizId啥的,如果單獨(dú)在每次調(diào)用的時(shí)候去配置這些重復(fù)的邏輯,顯然不合適。所以我們可以在Feign的攔截器中統(tǒng)一配置這些權(quán)限參數(shù)。
如何配置呢?其實(shí)很簡(jiǎn)單。
import org.springframework.context.annotation.Configuration; import org.springframework.web.context.request.RequestContextHolder; import org.springframework.web.context.request.ServletRequestAttributes; import feign.RequestInterceptor; import feign.RequestTemplate; import javax.servlet.http.HttpServletRequest; import java.util.Enumeration; ? @Configuration public class FeignConfiguration implements RequestInterceptor { ? ? @Override ? ? public void apply(RequestTemplate template) { ? ? ? ? ServletRequestAttributes attributes = (ServletRequestAttributes) ? ? ? ? ? ? ? ? RequestContextHolder.getRequestAttributes(); ? ? ? ? HttpServletRequest request = attributes.getRequest(); ? ? ? ? Enumeration<String> headerNames = request.getHeaderNames(); ? ? ? ? if (headerNames != null) { ? ? ? ? ? ? while (headerNames.hasMoreElements()) { ? ? ? ? ? ? ? ? String name = headerNames.nextElement(); ? ? ? ? ? ? ? ? String values = request.getHeader(name); ? ? ? ? ? ? ? ? template.header(name, values); ? ? ? ? ? ? } ? ? ? ? } ? ? } }
然后再feignClient中配置自定義的配置類,覆蓋默認(rèn)的配置
@Component @FeignClient(value = "feignTest" ,configuration = FeignConfiguration.class) public interface FeignTestService { }
這樣就所有的Feign調(diào)用都會(huì)在Header調(diào)用中加上request中傳遞過來的參數(shù)。不需要單獨(dú)在每次Feign調(diào)用重復(fù)添加參數(shù)。
通過@RequestHeader注解
上面也說到,我們?cè)跀r截器中獲取request傳遞過來的參數(shù),然后再放到header中。在攔截器中配置的一般都是公用的一些參數(shù)。
但是如果一個(gè)服務(wù)接口,需要一些特殊參數(shù)。但是其他服務(wù)不需要這個(gè)參數(shù),這時(shí)候我們不必在攔截器中配置其他服務(wù)不需要的參數(shù),只需在需要的服務(wù)接口上加上@RequestHeader注解,然后在feign調(diào)用的時(shí)候把參數(shù)傳過來就ok了。
@PostMapping(value = "/orderDetails") public ReturnInfo getOrderDetail(@RequestHeader(name = "id") String orderId);
比如說之前在quartz中通過Feign調(diào)用其他服務(wù)獲取優(yōu)惠券信息,項(xiàng)目中封裝的方法獲取的attributes 是空的。
ServletRequestAttributes attributes = (ServletRequestAttributes) ? ? ? ? ? ? ? ? RequestContextHolder.getRequestAttributes();
這時(shí)候就不用攔截器了,直接在方法入?yún)⑸霞由?@RequestHeader注解。
這里簡(jiǎn)單介紹下Feign調(diào)用的傳參,實(shí)際在項(xiàng)目中,大家對(duì)Feign調(diào)用方法都有自己的封裝,代碼和上面的可能不一樣,但是原理都是差不多的。
調(diào)用feign接口時(shí),如何往header中添加參數(shù)
Controller接收到請(qǐng)求后,我們可以在service中通過feign直接調(diào)用其它服務(wù)的接口,但是,controller接收到的請(qǐng)求和通過feign調(diào)用其它服務(wù),其它服務(wù)接收到的請(qǐng)求,是不一樣的。例如我們往往習(xí)慣于在header中放入用戶的token信息,在不做處理的情況下,其它服務(wù)接收到的請(qǐng)求,可能就是無用戶信息狀態(tài),這種請(qǐng)求應(yīng)該判定為無效狀態(tài)。
在服務(wù)的提供方或者調(diào)用方定義一個(gè)攔截器,將當(dāng)前請(qǐng)求的token信息手動(dòng)添加到feign請(qǐng)求的header中。
@Configuration public class FeignRequestInterceptorConfig implements RequestInterceptor { @Bean public RequestContextListener requestContextListener() { return new RequestContextListener(); } @Override public void apply(RequestTemplate requestTemplate) { ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes(); if (ObjectUtils.isEmpty(attributes)) { return; } HttpServletRequest request = attributes.getRequest(); String token = request.getHeader("token"); requestTemplate.header("token", token); } }
在使用過程中,可能會(huì)涉及到在請(qǐng)求方獲取自己的token信息都是為空的,查看一下是否是Hystrix策略導(dǎo)致的,如下配置可以解決該問題。
hystrix: command: default: execution: timeout: #如果enabled設(shè)置為false,則請(qǐng)求超時(shí)交給ribbon控制 enabled: true isolation: # 隔離策略 strategy: SEMAPHORE thread: timeoutInMilliseconds: 100000
總結(jié)
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
淺談Java中Collection和Collections的區(qū)別
下面小編就為大家?guī)硪黄獪\談Java中Collection和Collections的區(qū)別。小編覺得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2016-08-08SpringBoot整合Druid實(shí)現(xiàn)SQL監(jiān)控和數(shù)據(jù)庫(kù)密碼加密
Druid連接池是阿里巴巴開源的數(shù)據(jù)庫(kù)連接池項(xiàng)目,Druid連接池為監(jiān)控而生,內(nèi)置強(qiáng)大的監(jiān)控功能,監(jiān)控特性不影響性能,本文給大家介紹了SpringBoot整合Druid實(shí)現(xiàn)SQL監(jiān)控和數(shù)據(jù)庫(kù)密碼加密,文中有相關(guān)的代碼示例供大家參考,需要的朋友可以參考下2024-06-06Java對(duì)象比較之equals與hashCode詳解
這篇文章主要介紹了Java對(duì)象比較之equals與hashCode詳解,equals?方法和?hashCode?方法是?Object?類中的兩個(gè)基礎(chǔ)方法,它們共同協(xié)作來判斷兩個(gè)對(duì)象是否相等,需要的朋友可以參考下2023-12-12SpringBoot實(shí)現(xiàn)文件上傳下載功能小結(jié)
最近做的一個(gè)項(xiàng)目涉及到文件上傳與下載功能。SpringBoot后臺(tái)如何實(shí)現(xiàn)文件上傳下載呢?下面有單文件上傳和多文件上傳功能,感興趣的朋友一起看看吧2017-08-08解決spring 處理request.getInputStream()輸入流只能讀取一次問題
這篇文章主要介紹了解決spring 處理request.getInputStream()輸入流只能讀取一次問題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧2020-09-09淺談springfox-swagger原理解析與使用過程中遇到的坑
本篇文章主要介紹了淺談springfox-swagger原理解析與使用過程中遇到的坑,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2018-02-02