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

SpringMVC之RequestContextHolder詳細(xì)解析

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

前言

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

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

1.RequestContextHolder的使用

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

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

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

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

2.解決疑問

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

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

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

再看`getRequestAttributes()`方法,相當(dāng)于直接獲取ThreadLocal里面的值,這樣就保證了每一次獲取到的Request是該請求的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è)的話需要對springMVC結(jié)構(gòu)的`DispatcherServlet`的結(jié)構(gòu)有一定了解才能準(zhǔn)確的定位該去哪里找相關(guān)代碼.

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

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

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

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

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

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

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

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

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

  1. 獲取上一個(gè)請求的參數(shù)
  2. 重新建立新的參數(shù)
  3. 設(shè)置到XXContextHolder
  4. 父類的service()處理請求
  5. 恢復(fù)request
  6. 發(fā)布事
protected final void processRequest(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
long startTime = System.currentTimeMillis();
Throwable failureCause = null;
//獲取上一個(gè)請求保存的LocaleContext
    LocaleContext previousLocaleContext = LocaleContextHolder.getLocaleContext();
//建立新的LocaleContext
    LocaleContext localeContext = buildLocaleContext(request);
//獲取上一個(gè)請求保存的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í)際上保存的類型為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è)類相比`RequestAttributes`方法是多了很多

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

相關(guān)文章

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

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

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

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

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

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

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

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

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

    Spring事務(wù)失效之常見場景分析

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

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

    這篇文章主要為大家詳細(xì)介紹了cookie、session和java過濾器結(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ù)、注釋類型,編譯器會(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à)值,希望對大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2021-11-11
  • Springboot跨域處理的多種方式小結(jié)

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

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

最新評論

松阳县| 苏尼特左旗| 扶绥县| 肥东县| 广汉市| 深州市| 彩票| 五大连池市| 定陶县| 沂源县| 文昌市| 衢州市| 德兴市| 麟游县| 玉山县| 曲阜市| 玛沁县| 瓮安县| 广汉市| 交口县| 肃宁县| 鹤峰县| 汾阳市| 苍溪县| 营口市| 富源县| 洛阳市| 镇巴县| 黔南| 姚安县| 永安市| 古交市| 广灵县| 龙口市| 青海省| 桃江县| 盐池县| 洛宁县| 仁寿县| 且末县| 饶阳县|