久久r热视频,国产午夜精品一区二区三区视频,亚洲精品自拍偷拍,欧美日韩精品二区

您的位置:首頁(yè)技術(shù)文章
文章詳情頁(yè)

如何在Spring WebFlux的任何地方獲取Request對(duì)象

瀏覽:118日期:2023-07-25 11:51:14
1 不一樣的世界

在常規(guī)的Spring Web項(xiàng)目中,我們要獲取Request對(duì)象是非常方便的,不少庫(kù)都提供了靜態(tài)方法來(lái)獲取。獲取代碼如下:

ServletRequestAttributes requestAttributes = (ServletRequestAttributes)RequestContextHolder.getRequestAttributes();// get the requestHttpServletRequest request = requestAttributes.getRequest();

在類(lèi)RequestContextHolder提供了靜態(tài)方法,也就意味著你可以在任何地方調(diào)用。而它使用了ThreadLocal來(lái)保存Request對(duì)象,也就是不同線程是可以獲取各自的Request對(duì)象。

但在響應(yīng)式WebFlux的世界里,并沒(méi)有提供類(lèi)似的Holder類(lèi),而WebFlux是無(wú)法感知線程的,任何一個(gè)線程可以在任何時(shí)候處理任何請(qǐng)求,如果它覺(jué)得切換當(dāng)前線程更有效率,它就會(huì)這么做。但在Servlet Based的應(yīng)用里,它會(huì)為某個(gè)請(qǐng)求安排一個(gè)線程去處理完整個(gè)過(guò)程。

這個(gè)巨大的差別,意味著不能簡(jiǎn)單地通過(guò)ThreadLocal來(lái)保存和獲取Request了。

2 先保存,再獲取

為了在后面可以方便獲得Request對(duì)象,我們就需要在開(kāi)始的時(shí)候把它存在一個(gè)可以使用、并且是相同scope的容器里。這里需要解決兩個(gè)關(guān)鍵問(wèn)題:

(1)Request對(duì)象從何而來(lái);

(2)存在哪里?

針對(duì)問(wèn)題(1), 我們可以回想什么時(shí)候會(huì)出現(xiàn)Request對(duì)象,最容易想得到的就是WebFilter了,它的方法簽名如下:

public Mono<Void> filter(ServerWebExchange exchange, WebFilterChain chain);

我們可以通過(guò)ServerWebExchange直接獲取到Request對(duì)象:

ServerHttpRequest request = exchange.getRequest();

而因?yàn)镕ilter是可以先于應(yīng)用邏輯執(zhí)行的,所以滿足要求,問(wèn)題(1)解決。

針對(duì)問(wèn)題(2),需要一個(gè)與Reavtive請(qǐng)求相同范圍的容器,reactor.util.context.Context可以滿足需求。查看reactor的官方文檔(https://projectreactor.io/docs/core/release/reference/#context )可見(jiàn)下面這段話:

Since version 3.1.0, Reactor comes with an advanced feature that is somewhat comparable to ThreadLocal but can be applied to a Flux or a Mono instead of a Thread. This feature is called Context.

并且官網(wǎng)也給出了為何ThreadLocal在某些場(chǎng)景不適用的解釋?zhuān)信d趣可以看看。

3 代碼實(shí)現(xiàn)3.1 WebFilter獲取并保存

首先,在WebFilter中獲取Request對(duì)象并保存,代碼如下:

@Configuration@ConditionalOnWebApplication(type = ConditionalOnWebApplication.Type.REACTIVE)public class ReactiveRequestContextFilter implements WebFilter { @Override public Mono<Void> filter(ServerWebExchange exchange, WebFilterChain chain) { ServerHttpRequest request = exchange.getRequest(); return chain.filter(exchange).subscriberContext(ctx -> ctx.put(ReactiveRequestContextHolder.CONTEXT_KEY, request)); }}

從ServerWebExchange中獲取到ServerHttpRequest對(duì)象,再通過(guò)put方法把它放進(jìn)Context里。

3.2 工具類(lèi)Holder

實(shí)現(xiàn)一個(gè)工具類(lèi)來(lái)提供靜態(tài)方法,在Filter后的任何場(chǎng)景都可以使用:

public class ReactiveRequestContextHolder { public static final Class<ServerHttpRequest> CONTEXT_KEY = ServerHttpRequest.class; public static Mono<ServerHttpRequest> getRequest() { return Mono.subscriberContext().map(ctx -> ctx.get(CONTEXT_KEY)); }}3.3 在Controller中使用

我們嘗試在Controller中使用ReactiveRequestContextHolder來(lái)獲取Request:

@RestControllerpublic class GetRequestController { @RequestMapping('/request') public Mono<String> getRequest() { return ReactiveRequestContextHolder.getRequest().map(request -> request.getHeaders().getFirst('user')); }}

上面方法獲取了Request對(duì)象,然后再獲取了Request中的Header。

啟動(dòng)應(yīng)用,測(cè)試如下:

$ curl http://localhost:8088/request -H ’user: pkslow’pkslow$ curl http://localhost:8088/request -H ’user: larry’larry$ curl http://localhost:8088/request -H ’user: www.pkslow.com’www.pkslow.com

可以成功獲取請(qǐng)求頭user。

4 總結(jié)

代碼請(qǐng)查看:https://github.com/LarryDpk/pkslow-samples

以上就是如何在Spring WebFlux的任何地方獲取Request對(duì)象的詳細(xì)內(nèi)容,更多關(guān)于Spring WebFlux獲取Request對(duì)象的資料請(qǐng)關(guān)注好吧啦網(wǎng)其它相關(guān)文章!

標(biāo)簽: Spring
相關(guān)文章:
主站蜘蛛池模板: 来安县| 京山县| 西乡县| 礼泉县| 临潭县| 广河县| 大庆市| 班玛县| 十堰市| 莱阳市| 宜宾县| 中阳县| 来凤县| 连平县| 汶上县| 富裕县| 芒康县| 丰原市| 抚顺市| 双城市| 原阳县| 叙永县| 光山县| 新丰县| 梁山县| 禄劝| 尉犁县| 加查县| 瑞金市| 房产| 拉萨市| 阿瓦提县| 子洲县| 上高县| 家居| 林周县| 伊川县| 东乌珠穆沁旗| 临洮县| 利津县| 平山县|