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

SpringMVC中RequestContextHolder獲取請求信息的方法

 更新時間:2020年04月03日 10:05:38   作者:昂蒂梵德  
這篇文章主要介紹了SpringMVC中RequestContextHolder獲取請求信息的方法,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧

RequestContextHolder的作用是:

在Service層獲取獲取request和response信息

代碼示例:

 ServletRequestAttributes attrs = (ServletRequestAttributes)RequestContextHolder.getRequestAttributes();
HttpServletRequest request = attrs.getRequest();

源碼分析:

定義了兩個ThreadLocal變量用來存儲Request

 private static final ThreadLocal<RequestAttributes> requestAttributesHolder = new NamedThreadLocal("Request attributes");
  private static final ThreadLocal<RequestAttributes> inheritableRequestAttributesHolder = new NamedInheritableThreadLocal("Request context");

設(shè)置方法

  public static void setRequestAttributes(@Nullable RequestAttributes attributes) {
    setRequestAttributes(attributes, false);
  }

  public static void setRequestAttributes(@Nullable RequestAttributes attributes, boolean inheritable) {
    if (attributes == null) {
      resetRequestAttributes();
    } else if (inheritable) {
      inheritableRequestAttributesHolder.set(attributes);
      requestAttributesHolder.remove();
    } else {
      requestAttributesHolder.set(attributes);
      inheritableRequestAttributesHolder.remove();
    }

  }

是在SpringMVC處理Servlet的類FrameworkServlet的類中,doget/dopost方法,調(diào)用processRequest方法進(jìn)行初始化上下文方法中initContextHolders設(shè)置進(jìn)去的

 private void initContextHolders(HttpServletRequest request, @Nullable LocaleContext localeContext, @Nullable RequestAttributes requestAttributes) {
    if (localeContext != null) {
      LocaleContextHolder.setLocaleContext(localeContext, this.threadContextInheritable);
    }

    if (requestAttributes != null) {
      RequestContextHolder.setRequestAttributes(requestAttributes, this.threadContextInheritable);
    }

    if (this.logger.isTraceEnabled()) {
      this.logger.trace("Bound request context to thread: " + request);
    }

  }

再看一下請求信息怎么獲取

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

    return attributes;
  }

解決疑問

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

首先分析RequestContextHolder這個類,里面有兩個ThreadLocal保存當(dāng)前線程下的request,關(guān)于ThreadLocal可以參考我的另一篇博文[Java學(xué)習(xí)記錄--ThreadLocal使用案例]

//得到存儲進(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;
  }

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

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

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

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

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

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

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

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

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

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

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

  1. 獲取上一個請求的參數(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;
//獲取上一個請求保存的LocaleContext
  LocaleContext previousLocaleContext = LocaleContextHolder.getLocaleContext();
//建立新的LocaleContext
  LocaleContext localeContext = buildLocaleContext(request);
//獲取上一個請求保存的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,這也是為什么在使用的時候可以把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,這個類相比`RequestAttributes`方法是多了很多.

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

相關(guān)文章

  • 解決IDEA使用Spring Initializr創(chuàng)建項(xiàng)目時無法連接到https://start.spring.io的問題

    解決IDEA使用Spring Initializr創(chuàng)建項(xiàng)目時無法連接到https://start.spring.io的問

    這篇文章主要介紹了解決IDEA使用Spring Initializr創(chuàng)建項(xiàng)目時無法連接到https://start.spring.io的問題,本文通過圖文并茂的形式給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2020-04-04
  • Java IO之File 類詳解

    Java IO之File 類詳解

    這篇文章主要為大家介紹了vue組件通信的幾種方法,具有一定的參考價值,感興趣的小伙伴們可以參考一下,希望能夠給你帶來幫助
    2022-01-01
  • 解決springboot文件配置端口不起作用(默認(rèn)8080)

    解決springboot文件配置端口不起作用(默認(rèn)8080)

    這篇文章主要介紹了解決springboot文件配置端口不起作用(默認(rèn)8080),具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2021-08-08
  • Java+OpenCV實(shí)現(xiàn)人臉檢測并自動拍照

    Java+OpenCV實(shí)現(xiàn)人臉檢測并自動拍照

    這篇文章主要為大家詳細(xì)介紹了Java+OpenCV實(shí)現(xiàn)人臉檢測,并調(diào)用筆記本攝像頭實(shí)時抓拍,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2019-07-07
  • SpringBoot Bean被加載時進(jìn)行控制

    SpringBoot Bean被加載時進(jìn)行控制

    很多時候我們需要根據(jù)不同的條件在容器中加載不同的Bean,或者根據(jù)不同的條件來選擇是否在容器中加載某個Bean,這就是Bean的加載控制,一般我們可以通過編程式或注解式兩種不同的方式來完成Bean的加載控制
    2023-02-02
  • 淺談javaSE GUI (Action事件)

    淺談javaSE GUI (Action事件)

    下面小編就為大家?guī)硪黄獪\談javaSE GUI (Action事件)。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2016-06-06
  • 深入淺出重構(gòu)Mybatis與Spring集成的SqlSessionFactoryBean(上)

    深入淺出重構(gòu)Mybatis與Spring集成的SqlSessionFactoryBean(上)

    通常來講,重構(gòu)是指不改變功能的情況下優(yōu)化代碼,但本文所說的重構(gòu)也包括了添加功能。這篇文章主要介紹了重構(gòu)Mybatis與Spring集成的SqlSessionFactoryBean(上)的相關(guān)資料,需要的朋友可以參考下
    2016-11-11
  • Java中的密碼加密方式

    Java中的密碼加密方式

    文章介紹了Java中使用MD5算法對密碼進(jìn)行加密的方法,以及如何通過加鹽和多重加密來提高密碼的安全性,MD5是一種不可逆的哈希算法,適合用于存儲密碼,因?yàn)槠漭敵龅恼L度固定,且不容易發(fā)生碰撞,此外,通過加鹽和多重加密,可以進(jìn)一步增加密碼的復(fù)雜性和安全性
    2025-01-01
  • Mybatis返回類型為Map時遇到的類型轉(zhuǎn)化的異常問題

    Mybatis返回類型為Map時遇到的類型轉(zhuǎn)化的異常問題

    這篇文章主要介紹了Mybatis返回類型為Map時遇到的類型轉(zhuǎn)化的異常問題,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2023-12-12
  • java編程常用技術(shù)(推薦)

    java編程常用技術(shù)(推薦)

    下面小編就為大家?guī)硪黄猨ava編程常用技術(shù)(推薦)。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2016-06-06

最新評論

营山县| 宁陕县| 江口县| 承德县| 武陟县| 江山市| 金寨县| 鹰潭市| 翼城县| 曲松县| 保靖县| 禄劝| 石嘴山市| 双桥区| 崇明县| 盐边县| 容城县| 水城县| 大兴区| 西吉县| 清远市| 深水埗区| 庆阳市| 什邡市| 报价| 湖口县| 西宁市| 株洲市| 阜新| 德州市| 综艺| 中方县| 成安县| 德兴市| 白玉县| 金堂县| 体育| 和顺县| 巴彦淖尔市| 襄城县| 锦屏县|