欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

如何在Spring WebFlux的任何地方獲取Request對象

 更新時間:2021年01月26日 10:53:06   作者:南瓜慢說  
這篇文章主要介紹了如何在Spring WebFlux的任何地方獲取Request對象,幫助大家更好的理解和使用springboot框架,感興趣的朋友可以了解下

1 不一樣的世界

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

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

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

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

這個巨大的差別,意味著不能簡單地通過ThreadLocal來保存和獲取Request了。

2 先保存,再獲取

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

(1)Request對象從何而來;

(2)存在哪里?

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

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

我們可以通過ServerWebExchange直接獲取到Request對象:

ServerHttpRequest request = exchange.getRequest();

而因為Filter是可以先于應(yīng)用邏輯執(zhí)行的,所以滿足要求,問題(1)解決。

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

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在某些場景不適用的解釋,有興趣可以看看。

3 代碼實現(xiàn)

3.1 WebFilter獲取并保存

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

@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對象,再通過put方法把它放進(jìn)Context里。

3.2 工具類Holder

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

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來獲取Request

@RestController
public class GetRequestController {

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

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

啟動應(yīng)用,測試如下:

$ 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

可以成功獲取請求頭user。

4 總結(jié)

代碼請查看:https://github.com/LarryDpk/pkslow-samples

以上就是如何在Spring WebFlux的任何地方獲取Request對象的詳細(xì)內(nèi)容,更多關(guān)于Spring WebFlux獲取Request對象的資料請關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • Java SpringBoot容器注入對象詳解

    Java SpringBoot容器注入對象詳解

    本文通過實例代碼給大家詳解了springboot獲取ioc容器中注入的bean問題,非常不錯,具有一定的參考借鑒價值,需要的朋友參考下吧
    2021-09-09
  • 詳解java中的PropertyChangeSupport與PropertyChangeListener

    詳解java中的PropertyChangeSupport與PropertyChangeListener

    這篇文章主要介紹了詳解java中的PropertyChangeSupport與PropertyChangeListener的相關(guān)資料,需要的朋友可以參考下
    2017-09-09
  • 出現(xiàn)log.info報紅的解決方案

    出現(xiàn)log.info報紅的解決方案

    這篇文章主要介紹了出現(xiàn)log.info報紅的解決方案,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-06-06
  • Java使用NIO優(yōu)化IO實現(xiàn)文件上傳下載功能

    Java使用NIO優(yōu)化IO實現(xiàn)文件上傳下載功能

    IO 是基于流來讀取的,而NIO則是基于塊讀取,面向流 的 I/O 系統(tǒng)一次一個字節(jié)地處理數(shù)據(jù),這篇文章主要介紹了Java使用NIO優(yōu)化IO實現(xiàn)文件上傳下載功能,需要的朋友可以參考下
    2022-07-07
  • Java中防止數(shù)據(jù)重復(fù)提交超簡單的6種方法

    Java中防止數(shù)據(jù)重復(fù)提交超簡單的6種方法

    在平時開發(fā)中,如果網(wǎng)速比較慢的情況下,用戶提交表單后,發(fā)現(xiàn)服務(wù)器半天都沒有響應(yīng),那么用戶可能會以為是自己沒有提交表單,就會再點擊提交按鈕重復(fù)提交表單,這篇文章主要給大家介紹了關(guān)于Java中防止數(shù)據(jù)重復(fù)提交超簡單的6種方法,需要的朋友可以參考下
    2021-11-11
  • Java關(guān)鍵字finally_動力節(jié)點Java學(xué)院整理

    Java關(guān)鍵字finally_動力節(jié)點Java學(xué)院整理

    java關(guān)鍵字finally不管是否出現(xiàn)異常,finally子句總是在塊完成之前執(zhí)行。下面通過實現(xiàn)代碼給大家介紹Java關(guān)鍵字finally相關(guān)知識,需要的的朋友參考下吧
    2017-04-04
  • SpringBoot常用讀取配置文件的3種方法小結(jié)

    SpringBoot常用讀取配置文件的3種方法小結(jié)

    本文主要介紹了SpringBoot常用讀取配置文件的3種方法小結(jié),主要包括@Value讀取配置文件,@ConfigurationProperties 讀取配置文件和讀取配置文件中的List,具有一定的參考價值,感興趣的可以了解一下
    2023-10-10
  • java設(shè)計模式之實現(xiàn)對象池模式示例分享

    java設(shè)計模式之實現(xiàn)對象池模式示例分享

    對象池模式經(jīng)常用在頻繁創(chuàng)建、銷毀對象(并且對象創(chuàng)建、銷毀開銷很大)的場景,比如數(shù)據(jù)庫連接池、線程池、任務(wù)隊列池等。本代碼簡單,沒有限制對象池大小
    2014-02-02
  • linux重啟java服務(wù)的腳本

    linux重啟java服務(wù)的腳本

    這篇文章主要介紹了linux重啟java服務(wù)的腳本,本文分步驟通過shell腳本給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2022-07-07
  • 如何解決異步任務(wù)上下文丟失問題

    如何解決異步任務(wù)上下文丟失問題

    在多線程編程中,異步任務(wù)可能會導(dǎo)致上下文信息丟失,為了解決這個問題,可以在執(zhí)行異步任務(wù)前,通過自定義TaskDecorator拷貝主線程的上下文至子線程,這樣可以確保上下文在異步執(zhí)行過程中得以保留,將定制的TaskDecorator設(shè)置至線程池,可以有效地解決上下文丟失問題
    2024-09-09

最新評論