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

SpringMVC中RequestContextHolder獲取請(qǐng)求信息的方法

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

RequestContextHolder的作用是:

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

代碼示例:

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

源碼分析:

定義了兩個(gè)ThreadLocal變量用來(lái)存儲(chǔ)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的類(lèi)FrameworkServlet的類(lèi)中,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);
    }

  }

再看一下請(qǐng)求信息怎么獲取

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

    return attributes;
  }

解決疑問(wèn)

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

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

//得到存儲(chǔ)進(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是該請(qǐng)求的request.

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

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

找這個(gè)的話需要對(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獲取請(qǐng)求信息的方法的文章就介紹到這了,更多相關(guān)SpringMVC RequestContextHolder請(qǐng)求信息內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Java List按照某字段去重的使用示例

    Java List按照某字段去重的使用示例

    在Java開(kāi)發(fā)中,我們經(jīng)常會(huì)面臨對(duì)List中對(duì)象屬性去重的需求,本文主要介紹了Java List按照某字段去重的使用示例,具有一定的參考價(jià)值,感興趣的可以了解一下
    2023-12-12
  • 詳解Java數(shù)據(jù)庫(kù)連接池

    詳解Java數(shù)據(jù)庫(kù)連接池

    今天繼續(xù)Java的課題,兩天沒(méi)有做任何事情,過(guò)了個(gè)自在的周末,但是不知道為什么總是有點(diǎn)淡淡的憂桑.之前游戲服務(wù)器的數(shù)據(jù)源使用的是阿里巴巴的Druid,今天就大概說(shuō)說(shuō)數(shù)據(jù)源,給個(gè)實(shí)例,需要的朋友可以參考下
    2021-06-06
  • 詳解Java中String,StringBuffer和StringBuilder的使用

    詳解Java中String,StringBuffer和StringBuilder的使用

    這篇文章主要為大家詳細(xì)介紹了Java中String,StringBuffer和StringBuilder三者的區(qū)別以及使用,文中的少了講解詳細(xì),感興趣的可以了解一下
    2022-07-07
  • spring boot高并發(fā)下耗時(shí)操作的實(shí)現(xiàn)方法

    spring boot高并發(fā)下耗時(shí)操作的實(shí)現(xiàn)方法

    這篇文章主要給大家介紹了關(guān)于spring boot高并發(fā)下耗時(shí)操作的實(shí)現(xiàn)方法,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家學(xué)習(xí)或者使用spring boot具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2019-11-11
  • tomcat部署java web項(xiàng)目遇到的問(wèn)題及解決方法

    tomcat部署java web項(xiàng)目遇到的問(wèn)題及解決方法

    這篇文章主要介紹了tomcat部署java web項(xiàng)目遇到的問(wèn)題及解決方法,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2019-07-07
  • java15新功能的詳細(xì)講解

    java15新功能的詳細(xì)講解

    這篇文章主要介紹了java15的新功能,雖然java15并不是長(zhǎng)期支持的版本,但是很多新功能還是很有用的。感興趣的小伙伴可以參考一下
    2021-08-08
  • 詳解maven安裝教程以及解決安裝不成功的解決辦法

    詳解maven安裝教程以及解決安裝不成功的解決辦法

    這篇文章主要介紹了詳解maven安裝教程以及解決安裝不成功的解決辦法,詳細(xì)的介紹了幾種解決方法,非常具有實(shí)用價(jià)值,需要的朋友可以參考下
    2018-12-12
  • Java深入講解AWT實(shí)現(xiàn)事件處理流程

    Java深入講解AWT實(shí)現(xiàn)事件處理流程

    AWT的事件處理是一種委派式事件處理方式:普通組件(事件源)將整個(gè)事件處理委托給特定的對(duì)象(事件監(jiān)聽(tīng)器);當(dāng)該事件源發(fā)生指定的事件時(shí),就通知所委托的事件監(jiān)聽(tīng)器,由事件監(jiān)聽(tīng)器來(lái)處理這個(gè)事件
    2022-04-04
  • Java多線程的原子性,可見(jiàn)性,有序性你都了解嗎

    Java多線程的原子性,可見(jiàn)性,有序性你都了解嗎

    這篇文章主要為大家詳細(xì)介紹了Java多線程的原子性,可見(jiàn)性,有序性,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下,希望能夠給你帶來(lái)幫助
    2022-03-03
  • SpringBoot+RabbitMQ方式收發(fā)消息的實(shí)現(xiàn)示例

    SpringBoot+RabbitMQ方式收發(fā)消息的實(shí)現(xiàn)示例

    這篇文章主要介紹了SpringBoot+RabbitMQ方式收發(fā)消息的實(shí)現(xiàn)示例,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2020-09-09

最新評(píng)論