最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

feign微服務(wù)之間傳遞請求頭數(shù)據(jù)方式

 更新時間:2026年03月19日 08:40:36   作者:一定不晚睡啊  
這篇文章主要介紹了feign微服務(wù)之間傳遞請求頭數(shù)據(jù)方式,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教

直接在微服務(wù)遠(yuǎn)程調(diào)用中獲取請求頭數(shù)據(jù)不能直接獲取到.為什么? 看源碼

默認(rèn)情況下feign遠(yuǎn)程調(diào)用的時候不會傳遞請求頭!

遠(yuǎn)程調(diào)用源碼:

每一次遠(yuǎn)程請求的時候都創(chuàng)建了一個新的Request Template對象,在該對象中不包含之前的請求頭數(shù)據(jù)

解決方案

方案一

在feign接口上添加對應(yīng)的形式參數(shù)即可

弊端:每一個接口想要獲取參數(shù)都需要在接口方法上添加對應(yīng)的形式參數(shù).影響代碼效率

方案二

使用OpenFeign中的攔截器(RequestInterceptor)來攔截請求,添加請求頭。

方案一演示

FeignClient接口:

@FeignClient(value = "service-cart",fallback = FeignClientFallback.class)//降級方法
public interface FeignClient { 
public Result xxx( 
                  @RequestParam(value = "xx" )Long xx ,
                  @RequestParam(value = "xx" )String xx);
}

Controller遠(yuǎn)程接口:

@RestController
@RequestMapping("/x/x/x")
public class Controller {

    @GetMapping("/x/x/x")
    public Result aaa(
            @RequestParam(value = "xx" )Long xx ,
            @RequestParam(value = "xx" )String xx
             ) {
        return Result.ok() ;
    }
}

//@RequestParam 通過傳參的方法傳遞過去,并非從請求頭上拿
FeignClient.aaa(xx,xx); //遠(yuǎn)程調(diào)用時候傳參

方案二演示

思路:在OpenFeign遠(yuǎn)程調(diào)用 定義一個攔截器類實現(xiàn)(RequestInterceptor)接口給RequestTemplate設(shè)置上請求頭

核心源碼

// feign.SynchronousMethodHandler#executeAndDecode
Request targetRequest(RequestTemplate template) {        
    // 在構(gòu)建目標(biāo)請求對象的時候,遍歷所有的攔截器,
    //   然后調(diào)用了apply方法把RequestTemplate作為參數(shù)傳遞過去
    for (RequestInterceptor interceptor : requestInterceptors) {
        interceptor.apply(template);
    }
    return target.apply(template);
}

攔截器類如何獲取Controller請求頭數(shù)據(jù)呢?

  • 思路1:通過Map實現(xiàn)
  • 原理:feign的調(diào)用鏈?zhǔn)褂玫氖峭粋€線程對象
  • 思路2:通過ThreadLocal對象在一個線程中共享HttpServletRequest對象(使用JDK自帶的ThreadLocal在一個線程中共享HttpServletRequest對象,原理就是在底層維護(hù)了一個Map。)
  • 思路3: 使用spring提供的對象RequestContextHolder進(jìn)行實現(xiàn)!

原理:底層通過RequestContextListener監(jiān)聽器實現(xiàn)

思路1實現(xiàn):

  • 獲取Controller中請求頭思路:
  • feign的調(diào)用鏈?zhǔn)褂玫氖峭粋€線程對象
  • 所以可以在Controller中定義一個Map集合,鍵就是當(dāng)前線程對象,值就是HttpServletRequest對象
 //定義一個Map,作用是在tController和FeignClientInterceptor(攔截器)中共享HttpServletRequest
    public static final ConcurrentHashMap<Thread, HttpServletRequest> concurrentHashMap =new ConcurrentHashMap<>();

//給map中存request對象

@GetMapping("/xx")//required:傳遞過來的參數(shù)可以有可以無
    public String addCart(HttpServletRequest request, ) {

        concurrentHashMap.put(Thread.currentThread(),request);
}

攔截器類通過map獲取請求頭數(shù)據(jù),設(shè)置給RequestTemplate

@Component
@Slf4j
public class FeignClientInterceptor implements RequestInterceptor {
    @Override
    public void apply(RequestTemplate requestTemplate) {
        log.info("FeignClientInterceptor..........");
        HttpServletRequest httpServletRequest = CartController.concurrentHashMap.get(Thread.currentThread());
            //給requestTemplate 添加上對應(yīng)的請求頭中的數(shù)據(jù):aa,bbb
        requestTemplate.header("userId",httpServletRequest.getHeader("aa"));
        requestTemplate.header("userTempId",httpServletRequest.getHeader("bbb"));

    }
}

思路2實現(xiàn):

在Controller中定義一個ThreadLocal對象

public static final  ThreadLocal<HttpServletRequest> threadLocal = new ThreadLocal<>();

然后在方法中調(diào)用set方法添加數(shù)據(jù)(request)

threadLocal.set(request);

在攔截器中調(diào)用get方法就可以拿到HttpServletRequest對象,然后給requestTemplate 添加上對應(yīng)的請求頭中的數(shù)據(jù):aa,bbb

 HttpServletRequest httpServletRequest = CartController.threadLocal.get();

 requestTemplate.header("userId",httpServletRequest.getHeader("aa"));
 requestTemplate.header("userTempId",httpServletRequest.getHeader("bbb"));

思路3實現(xiàn):使用spring提供的對象RequestContextHolder直接在攔截器類獲取request對象

//RequestContextHolder對象中獲取一個線程內(nèi)所共享的HttpServletRequest對象
        ServletRequestAttributes servletRequestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        HttpServletRequest request = servletRequestAttributes.getRequest();
//獲取到了request對象剩下的同上

思路3的在Controller使用模塊中通過RequestContextHolder隱式獲取請求頭數(shù)據(jù)

直接在使用模塊獲取ServletRequestAttributes對象,不需要在參數(shù)添加@RequestHeader(value = "xxx")
因為剛才已經(jīng)用到了request對象
// 獲取ServletRequestAttributes對象
        ServletRequestAttributes requestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        HttpServletRequest requestAttributesRequest = requestAttributes.getRequest();
        String userId = requestAttributesRequest.getHeader("userId");
        String userTempId = requestAttributesRequest.getHeader("userTempId") ;

代碼優(yōu)化:

1.將從RequestContextHolder對象中讀取xx和xx數(shù)據(jù)的代碼封裝到一個工具類(utilxx),并使用一個實體類返回相關(guān)數(shù)據(jù):

public class Utils {

    public static UserInfoVo userInfo() {

        // 獲取請求對象
        ServletRequestAttributes requestAttributes 
        = (ServletRequestAttributes)RequestContextHolder.getRequestAttributes();

        // 判斷requestAttributes是否為空
        if(requestAttributes != null) {

            // 獲取request對象
            HttpServletRequest request = requestAttributes.getRequest();

            // 從請求對象中獲取xx和xx數(shù)據(jù)
            String userid = request.getHeader("id");
            String username = request.getHeader("name");

            // 封裝數(shù)據(jù)到xxx對象中
            User user = new user() ;
            if(!StringUtils.isEmpty(userId)) {
                userAuthInfoVo.setUserId(Long.parseLong(userId));
            }
            userAuthInfoVo.setUserTempId(username);

            // 返回
            return user ;
        }

        return null ;
    }

}

2.FeignClientInterceptor抽取成公共組件

為了實現(xiàn)FeignClientInterceptor的復(fù)用,那么此時可以將FeignClientInterceptor抽取成一個公共的組件

@Slf4j
@Component
public class FeignClientInterceptor implements RequestInterceptor {

    @Override
    public void apply(RequestTemplate template) {
        
        log.info("FeignClientInterceptor攔截器執(zhí)行了....");

        User user = User.getUser();
        if(user != null) {
            Long userId = user.getUserId();
            if(userId != null) {
                template.header("userId" , String.valueOf(userId)) ;
            }
            template.header("username" , userAuthInfo.getUsername()) ;
        }

    }

}

自定義注解:

因為抽取公共類后包路徑不一樣會導(dǎo)致掃描不到所以,可以使用自定義注解或@Import解決,這里使用自定義注解

@Target(value = ElementType.TYPE)
@Retention(value = RetentionPolicy.RUNTIME)
@Import(value = EnableFeignClientInterceptor.class)
public @interface EnableFeignClientInterceptor {
}

啟動類加上@EnableFeignClientIntercepto即可使用

總結(jié)

以上為個人經(jīng)驗,希望能給大家一個參考,也希望大家多多支持腳本之家。

相關(guān)文章

  • 使用java代碼獲取新浪微博應(yīng)用的access token代碼實例

    使用java代碼獲取新浪微博應(yīng)用的access token代碼實例

    這篇文章主要介紹了使用java代碼獲取新浪微博應(yīng)用的access token實例,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2019-05-05
  • Java 虛擬機(jī)棧詳解分析

    Java 虛擬機(jī)棧詳解分析

    在線程創(chuàng)建時,JVM會為每個線程創(chuàng)建一個單獨的??臻g。JVM的棧內(nèi)存不需要是連續(xù)的。JVM在棧上會進(jìn)行兩個操作:壓入和彈出棧幀。對于一個特定的線程來說,棧被稱為運行時棧。這個線程調(diào)用的每個方法會被存儲在響應(yīng)的運行時棧里,包括了參數(shù),局部變量,計算媒介和其他數(shù)據(jù)
    2021-11-11
  • 基于spring-security 401 403錯誤自定義處理方案

    基于spring-security 401 403錯誤自定義處理方案

    這篇文章主要介紹了基于spring-security 401 403錯誤自定義處理方案,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2021-07-07
  • 詳解SpringBoot Schedule配置

    詳解SpringBoot Schedule配置

    本篇文章主要介紹了詳解SpringBoot Schedule配置 ,可以實現(xiàn)定時任務(wù),小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2017-03-03
  • maven打包zip包含bin下啟動腳本的完整代碼

    maven打包zip包含bin下啟動腳本的完整代碼

    這篇文章主要介紹了maven打包zip包含bin下啟動腳本,本文給大家講解的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2021-10-10
  • Java logback日志的簡單使用

    Java logback日志的簡單使用

    這篇文章主要介紹了Java logback日志的使用詳解,幫助大家更好的理解和學(xué)習(xí)使用Java,感興趣的朋友可以了解下
    2021-03-03
  • Java實現(xiàn)并發(fā)執(zhí)行定時任務(wù)并手動控制開始結(jié)束

    Java實現(xiàn)并發(fā)執(zhí)行定時任務(wù)并手動控制開始結(jié)束

    這篇文章主要介紹了Java實現(xiàn)并發(fā)執(zhí)行定時任務(wù)并手動控制開始結(jié)束,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2024-05-05
  • 利用Kafka動態(tài)調(diào)整topic分區(qū)partition

    利用Kafka動態(tài)調(diào)整topic分區(qū)partition

    這篇文章主要介紹了利用Kafka動態(tài)調(diào)整topic分區(qū)partition問題,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-12-12
  • java基礎(chǔ)的詳細(xì)了解第四天

    java基礎(chǔ)的詳細(xì)了解第四天

    這篇文章對Java編程語言的基礎(chǔ)知識作了一個較為全面的匯總,在這里給大家分享一下。需要的朋友可以參考,希望能給你帶來幫助
    2021-08-08
  • spring?data?jpa查詢一個實體類的部分屬性方式

    spring?data?jpa查詢一個實體類的部分屬性方式

    這篇文章主要介紹了spring?data?jpa查詢一個實體類的部分屬性方式,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-02-02

最新評論

中牟县| 綦江县| 渝北区| 香港 | 屏边| 义马市| 电白县| 宣威市| 珠海市| 南陵县| 晋城| 芷江| 浦北县| 盐源县| 溆浦县| 凤城市| 赤峰市| 水城县| 平阴县| 安新县| 年辖:市辖区| 朔州市| 大英县| 大安市| 瑞丽市| 肥西县| 贞丰县| 岢岚县| 英德市| 连云港市| 玉门市| 玉林市| 清徐县| 渑池县| 儋州市| 靖边县| 佛教| 台州市| 阳春市| 石景山区| 高邮市|