91超碰碰碰碰久久久久久综合_超碰av人澡人澡人澡人澡人掠_国产黄大片在线观看画质优化_txt小说免费全本

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

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

發布時間:2020-08-21 23:13:42 來源:腳本之家 閱讀:1025 作者:昂蒂梵德 欄目:編程語言

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");

設置方法

  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方法,調用processRequest方法進行初始化上下文方法中initContextHolders設置進去的

 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怎么和當前請求掛鉤?

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

//得到存儲進去的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()`方法,相當于直接獲取ThreadLocal里面的值,這樣就保證了每一次獲取到的Request是該請求的request.

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

2request和response等是什么時候設置進去的?

找這個的話需要對springMVC結構的`DispatcherServlet`的結構有一定了解才能準確的定位該去哪里找相關代碼.

在IDEA中會顯示如下的繼承關系.

左邊1這里是Servlet的接口和實現類.

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

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

1. HttpServletBean 進行初始化工作

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

3. DispatcherServlet 具體分發處理.

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

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

  1. 獲取上一個請求的參數
  2. 重新建立新的參數
  3. 設置到XXContextHolder
  4. 父類的service()處理請求
  5. 恢復request
  6. 發布事
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());
//具體設置的方法
  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 {
//恢復
    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");
        }
      }
    }
//發布事件
    publishRequestHandledEvent(request, response, startTime, failureCause);
  }
}

再看initContextHolders(request, localeContext, requestAttributes)方法,把新的RequestAttributes設置進LocalThread,實際上保存的類型為ServletRequestAttributes,這也是為什么在使用的時候可以把RequestAttributes強轉為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`方法是多了很多.

到此這篇關于SpringMVC中RequestContextHolder獲取請求信息的方法的文章就介紹到這了,更多相關SpringMVC RequestContextHolder請求信息內容請搜索億速云以前的文章或繼續瀏覽下面的相關文章希望大家以后多多支持億速云!

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

白朗县| 揭东县| 东台市| 东莞市| 盈江县| 益阳市| 陈巴尔虎旗| 通化县| 九寨沟县| 璧山县| 锦州市| 织金县| 长汀县| 咸阳市| 临猗县| 泾川县| 依兰县| 商水县| 兴海县| 阿鲁科尔沁旗| 昌江| 吴江市| 南汇区| 霞浦县| 革吉县| 安阳县| 南阳市| 黄浦区| 永嘉县| 塘沽区| 北京市| 江油市| 平果县| 吉安县| 大余县| 成安县| 安岳县| 绩溪县| 吴堡县| 荥经县| 安国市|