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

SpringMVC之RequestContextHolder詳細(xì)解析

 更新時(shí)間:2023年11月28日 10:35:34   作者:ZhaoJuFei  
這篇文章主要介紹了SpringMVC之RequestContextHolder詳細(xì)解析,正常來(lái)說(shuō)在service層是沒(méi)有request的,然而直接從controlller傳過(guò)來(lái)的話(huà)解決方法太粗暴,后來(lái)發(fā)現(xiàn)了SpringMVC提供的RequestContextHolder,需要的朋友可以參考下

前言

最近遇到的問(wèn)題是在service獲取request和response,正常來(lái)說(shuō)在service層是沒(méi)有request的,然而直接從controlller傳過(guò)來(lái)的話(huà)解決方法太粗暴,后來(lái)發(fā)現(xiàn)了SpringMVC提供的RequestContextHolder遂去分析一番,并借此對(duì)SpringMVC的結(jié)構(gòu)深入了解一下,后面會(huì)再發(fā)文章詳細(xì)分析源碼。

ps:正常情況下,service應(yīng)該是無(wú)狀態(tài)的,這個(gè)RequestContextHolder可以在一些工具類(lèi)里使用。

1.RequestContextHolder的使用

RequestContextHolder顧名思義,持有上下文的Request容器.使用是很簡(jiǎn)單的,具體使用如下:

//兩個(gè)方法在沒(méi)有使用JSF的項(xiàng)目中是沒(méi)有區(qū)別的
RequestAttributes requestAttributes = RequestContextHolder.currentRequestAttributes();
//RequestContextHolder.getRequestAttributes();
//從session里面獲取對(duì)應(yīng)的值
String str = (String) requestAttributes.getAttribute("name",RequestAttributes.SCOPE_SESSION);
 
HttpServletRequest request = ((ServletRequestAttributes)requestAttributes).getRequest();
HttpServletResponse response = ((ServletRequestAttributes)requestAttributes).getResponse();

看到這一般都會(huì)想到幾個(gè)問(wèn)題:

  • request和response怎么和當(dāng)前請(qǐng)求掛鉤?
  • request和response等是什么時(shí)候設(shè)置進(jìn)去的?

2.解決疑問(wèn)

2.1 request和response怎么和當(dāng)前請(qǐng)求掛鉤?

首先分析RequestContextHolder這個(gè)類(lèi),里面有兩個(gè)ThreadLocal保存當(dāng)前線(xiàn)程下的request。

// 得到存儲(chǔ)進(jìn)去的request
private static final ThreadLocal<RequestAttributes> requestAttributesHolder =
new NamedThreadLocal<RequestAttributes>("Request attributes");
// 可被子線(xiàn)程繼承的request
private static final ThreadLocal<RequestAttributes> inheritableRequestAttributesHolder =
new NamedInheritableThreadLocal<RequestAttributes>("Request context");

再看`getRequestAttributes()`方法,相當(dāng)于直接獲取ThreadLocal里面的值,這樣就保證了每一次獲取到的Request是該請(qǐng)求的request.

public static RequestAttributes getRequestAttributes() {
        RequestAttributes attributes = requestAttributesHolder.get();
        if (attributes == null) {
            attributes = inheritableRequestAttributesHolder.get();
        }
        return attributes;
    }

2.2request和response等是什么時(shí)候設(shè)置進(jìn)去的?

找這個(gè)的話(huà)需要對(duì)springMVC結(jié)構(gòu)的`DispatcherServlet`的結(jié)構(gòu)有一定了解才能準(zhǔn)確的定位該去哪里找相關(guān)代碼.

在IDEA中會(huì)顯示如下的繼承關(guān)系.

左邊1這里是Servlet的接口和實(shí)現(xiàn)類(lèi).

右邊2這里是使得SpringMVC具有Spring的一些環(huán)境變量和Spring容器.類(lèi)似的XXXAware接口就是對(duì)該類(lèi)提供Spring感知,簡(jiǎn)單來(lái)說(shuō)就是如果想使用Spring的XXXX就要實(shí)現(xiàn)XXXAware,spring會(huì)把需要的東西傳送過(guò)來(lái).

那么剩下要分析的的就是三個(gè)類(lèi),簡(jiǎn)單看下源碼

1. HttpServletBean 進(jìn)行初始化工作

2. FrameworkServlet 初始化 WebApplicationContext,并提供service方法預(yù)處理請(qǐng)

3. DispatcherServlet 具體分發(fā)處理.

那么就可以在FrameworkServlet查看到該類(lèi)重寫(xiě)了service(),doGet(),doPost()...等方法,這些實(shí)現(xiàn)里面都有一個(gè)預(yù)處理方法`processRequest(request, response);`,所以定位到了我們要找的位置

查看`processRequest(request, response);`的實(shí)現(xiàn),具體可以分為三步:

  1. 獲取上一個(gè)請(qǐng)求的參數(shù)
  2. 重新建立新的參數(shù)
  3. 設(shè)置到XXContextHolder
  4. 父類(lèi)的service()處理請(qǐng)求
  5. 恢復(fù)request
  6. 發(fā)布事
protected final void processRequest(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
long startTime = System.currentTimeMillis();
Throwable failureCause = null;
//獲取上一個(gè)請(qǐng)求保存的LocaleContext
    LocaleContext previousLocaleContext = LocaleContextHolder.getLocaleContext();
//建立新的LocaleContext
    LocaleContext localeContext = buildLocaleContext(request);
//獲取上一個(gè)請(qǐng)求保存的RequestAttributes
    RequestAttributes previousAttributes = RequestContextHolder.getRequestAttributes();
//建立新的RequestAttributes
    ServletRequestAttributes requestAttributes = buildRequestAttributes(request, 
response, previousAttributes);
    WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request);
asyncManager.registerCallableInterceptor(FrameworkServlet.class.getName(), 
new RequestBindingInterceptor());
//具體設(shè)置的方法
    initContextHolders(request, localeContext, requestAttributes);
try {
        doService(request, response);
    }
catch (ServletException ex) {
failureCause = ex;
throw ex;
    }
catch (IOException ex) {
   failureCause = ex;
   throw ex;
    }
catch (Throwable ex) {
   failureCause = ex;
   throw new NestedServletException("Request processing failed", ex);
    }
finally {
//恢復(fù)
        resetContextHolders(request, previousLocaleContext, previousAttributes);
if (requestAttributes != null) {
requestAttributes.requestCompleted();
        }
if (logger.isDebugEnabled()) {
if (failureCause != null) {
this.logger.debug("Could not complete request", failureCause);
            }
else {
if (asyncManager.isConcurrentHandlingStarted()) {
                    logger.debug("Leaving response open for concurrent processing");
                }
else {
this.logger.debug("Successfully completed request");
                }
            }
        }
//發(fā)布事件
        publishRequestHandledEvent(request, response, startTime, failureCause);
    }
}

再看initContextHolders(request, localeContext, requestAttributes)方法,把新的RequestAttributes設(shè)置進(jìn)LocalThread,實(shí)際上保存的類(lèi)型為ServletRequestAttributes,這也是為什么在使用的時(shí)候可以把RequestAttributes強(qiáng)轉(zhuǎn)為ServletRequestAttributes.

private void initContextHolders(HttpServletRequest request, 
                                LocaleContext localeContext, 
                                RequestAttributes requestAttributes) {
if (localeContext != null) {
        LocaleContextHolder.setLocaleContext(localeContext, 
this.threadContextInheritable);
    }
if (requestAttributes != null) {
        RequestContextHolder.setRequestAttributes(requestAttributes, 
this.threadContextInheritable);
    }
if (logger.isTraceEnabled()) {
        logger.trace("Bound request context to thread: " + request);
    }
}

因此RequestContextHolder里面最終保存的為ServletRequestAttributes,這個(gè)類(lèi)相比`RequestAttributes`方法是多了很多

到此這篇關(guān)于SpringMVC之RequestContextHolder詳細(xì)解析的文章就介紹到這了,更多相關(guān)RequestContextHolder詳細(xì)解析內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Java連接mysql數(shù)據(jù)庫(kù)代碼實(shí)例程序

    Java連接mysql數(shù)據(jù)庫(kù)代碼實(shí)例程序

    這篇文章主要介紹了java連接mysql數(shù)據(jù)庫(kù)代碼實(shí)例程序,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2019-11-11
  • Socket編程簡(jiǎn)單示例(聊天服務(wù)器)

    Socket編程簡(jiǎn)單示例(聊天服務(wù)器)

    socket編程是在不同的進(jìn)程間進(jìn)行網(wǎng)絡(luò)通訊的一種協(xié)議,下面這篇文章主要給大家介紹了關(guān)于Socket編程簡(jiǎn)單示例的相關(guān)資料,文中通過(guò)實(shí)例代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2023-02-02
  • DragChartPanel可拖拽曲線(xiàn)應(yīng)用詳解

    DragChartPanel可拖拽曲線(xiàn)應(yīng)用詳解

    這篇文章主要為大家詳細(xì)介紹了DragChartPanel可拖拽曲線(xiàn)的應(yīng)用,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2019-12-12
  • java -D參數(shù)設(shè)置系統(tǒng)屬性無(wú)效問(wèn)題及解決

    java -D參數(shù)設(shè)置系統(tǒng)屬性無(wú)效問(wèn)題及解決

    這篇文章主要介紹了java -D參數(shù)設(shè)置系統(tǒng)屬性無(wú)效問(wèn)題及解決方案,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2022-12-12
  • Spring事務(wù)失效之常見(jiàn)場(chǎng)景分析

    Spring事務(wù)失效之常見(jiàn)場(chǎng)景分析

    這篇文章主要介紹了Spring事務(wù)失效之常見(jiàn)場(chǎng)景,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2023-04-04
  • cookie、session和java過(guò)濾器結(jié)合實(shí)現(xiàn)登陸程序

    cookie、session和java過(guò)濾器結(jié)合實(shí)現(xiàn)登陸程序

    這篇文章主要為大家詳細(xì)介紹了cookie、session和java過(guò)濾器結(jié)合實(shí)現(xiàn)登陸程序的具體代碼,感興趣的朋友可以參考一下
    2016-05-05
  • Java實(shí)現(xiàn)的計(jì)時(shí)器【秒表】功能示例

    Java實(shí)現(xiàn)的計(jì)時(shí)器【秒表】功能示例

    這篇文章主要介紹了Java實(shí)現(xiàn)的計(jì)時(shí)器【秒表】功能,結(jié)合實(shí)例形式分析了Java結(jié)合JFrame框架的計(jì)時(shí)器功能相關(guān)操作技巧,需要的朋友可以參考下
    2019-02-02
  • Spring注解之@Value詳解

    Spring注解之@Value詳解

    這篇文章主要介紹了Spring注解之@Value詳解,@Value可以修飾屬性、方法、參數(shù)、注釋類(lèi)型,編譯器會(huì)將?@Value注解的信息保留在?.class?文件中,并且能被虛擬機(jī)讀取,需要的朋友可以參考下
    2024-01-01
  • springboot啟動(dòng)時(shí)如何獲取端口和項(xiàng)目名

    springboot啟動(dòng)時(shí)如何獲取端口和項(xiàng)目名

    這篇文章主要介紹了springboot啟動(dòng)時(shí)如何獲取端口和項(xiàng)目名,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2021-11-11
  • Springboot跨域處理的多種方式小結(jié)

    Springboot跨域處理的多種方式小結(jié)

    當(dāng)一臺(tái)服務(wù)器資源從另一臺(tái)服務(wù)器(不同 的域名或者端口)請(qǐng)求一個(gè)資源或者接口,就會(huì)發(fā)起一個(gè)跨域 HTTP 請(qǐng)求,這篇文章主要介紹了Springboot跨域處理的多種方式小結(jié),需要的朋友可以參考下
    2023-11-11

最新評(píng)論

房产| 新蔡县| 钟山县| 门头沟区| 伊金霍洛旗| 莆田市| 大邑县| 迁西县| 高青县| 扶沟县| 正宁县| 西峡县| 民丰县| 桐城市| 右玉县| 娄烦县| 文山县| 武胜县| 波密县| 萝北县| 突泉县| 恩平市| 余干县| 将乐县| 察雅县| 阿克陶县| 濮阳县| 吴忠市| 双牌县| 平乡县| 柯坪县| 特克斯县| 喀什市| 武乡县| 绥阳县| 阿坝县| 扶余县| 平湖市| 乌恰县| 高州市| 两当县|