熱點推薦:
您现在的位置: 電腦知識網 >> 編程 >> Java編程 >> Java核心技術 >> 正文

JSF請求處理過程(二) 請求處理過程總覽

2022-06-13   來源: Java核心技術 

  請求處理過程總覽(FacesServlet#service)

  這總覽很明顯是看FacesServlet的service方法在FacesServlet的初始化過程中構造出了全局的FacesContextFactory對象和LifeCycle對象可以把FacesContextFactory看做是一個請求包裝工廠於是很明顯每當一個請求到達FacesServlet的時候第一步便是拿著請求到包裝工廠裡面包裝一下而包裝的結果就是一個FacesContext代碼如下

   FacesContext context = facesContextFactorygetFacesContext(servletConfiggetServletContext() request response lifecycle)

  在包裝過程中實際上是創建了一個ntextFacesContextImpl對象FacesContextImpl類繼承了jsfapi項目中的ntextFacesContextFacesContextImpl的構造方法的第一個參數是一個叫做ExternalContext的接口的實現查看其源代碼可以看到ExternalContextImpl類耦合了Servlet API而FacesContextImpl與Servlet API無關實際上在這裡做到了JSF可以不僅僅使用在Servlet環境中正如ExternalContext接口的注釋中所說在Servlet環境中使用JSF和在Portlet環境中使用JSF的不同實際上就是使用了不同的ExternalContext在FacesContextFactoryImpl中構造FacesContextImpl的代碼如下
  FacesContext ctx = new FacesContextImpl(new ExternalContextImpl((ServletContext) sc(ServletRequest) request(ServletResponse) response)lifecycle);

    FacesContextImpl的構造方法中還做了另外一件事情就是根據配置確定了RenderKitFactory顯然不同的RenderKitFactory可以產生不同的RenderKit而不同RenderKit對象是針對不同客戶端的所以對於浏覽器移動設備等等會有不同的RenderKitFacesContextImpl的構造方法中代碼如下
  thisexternalContext = ec;
setCurrentInstance(this);
thisrkFactory = (RenderKitFactory)FactoryFindergetFactory(FactoryFinderRENDER_KIT_FACTORY);

  在代碼中我們經常使用FacesContextgetCurrentInstance()這個靜態方法來獲取與當前請求對應的FacesContext對象實際上是在FacesContext類裡面有一個靜態的ThreadLocal對象用來存放了當前請求線程對應的FacesContext對象於是上面的代碼中setCurrentInstance(this)就是把當前構造出來的這個FacesContext對象放到了ThreadLocal裡面

  FacesContext創建出來以後正如上面所說要讓他經過LifeCycle這個Filter Chain的逐步處理了那麼Filter Chain裡面放的是一個一個Filter那麼LifeCycle這個Chain裡面放的是什麼呢?答案是Phases

  FacesServlet讓FaceContext通過LifeCycle的處理分成了兩個部分一個部分是調用LifeCycle的execute方法執行邏輯第二個部分是調用LifeCycle的render方法呈現響應FacesServletservice中代碼如下
  lifecycleexecute(context);
lifecyclerender(context);

  在LifeCycleImpl這個實現中存放了一個Phase對象的數組存放了個Phase其中第一個是null然後依次是視圖重建應用請求值驗證更新模型值執行應用程序呈現響應在execute方法中調用了從視圖重建開始到執行應用程序為止的個Phase而在render方法中調用了最後一個Phase也就是呈現響應在LifeCycleImpl類中代碼如下

  //The Phase instance for the render() method
    private Phase response = new RenderResponsePhase();

  // The set of Phase instances that are executed by the execute() method
    // in order by the ordinal property of each phase
    private Phase[] phases = {
        null // ANY_PHASE placeholder not a real Phase
        new RestoreViewPhase()
        new ApplyRequestValuesPhase()
        new ProcessValidationsPhase()
        new UpdateModelValuesPhase()
        new InvokeApplicationPhase()
        response
    };

  在Servlet Filter中可以由每一個Filter來決定是否要調用下一個Filter從而決定是否讓請求繼續通過Filter Chains中的後續Filter是鏈式調用的過程而在LifeCycle的execute方法中是用一個for循環順序執行幾個Phase在每一個Phase執行完之後都會檢查FaceContext對象中是否設置了停止後續處理直接呈現響應的標志(renderResponse)或者已經完成了響應無需後續處理也不需要經過呈現響應階段了(responseComplete)如果標志為true那麼就不再執行後續Phase

  LifeCycleImpl的execute方法主要代碼如下
  for (int i = len = phaseslength ; i < len; i++) { // Skip ANY_PHASE placeholder
 
              if (contextgetRenderResponse() ||
                  contextgetResponseComplete()) {
                  break;
              }
 
              phases[i]doPhase(context this listenerslistIterator());
 
  }

    在LifeCycle的render方法中也會檢查FacesContext的responseComplete狀態如果為true那麼就不再執行render Phase於是我們此刻知道了在我們自己所寫的一些代碼或者JSF庫裡面的一些代碼中調用FacesContext的responseComplete方法和renderResponse得作用原理render方法主要代碼如下
  if (!contextgetResponseComplete()) {
       responsedoPhase(context thislistenerslistIterator());
}

  另外注意Phase這個概念接口以及幾個實現都是jsfri項目中的而在jsfapi中不存在Phase這個概念所以LifeCycle是JSF標准的內容而通過幾個Phase來處理請求這種實現是sun的參考實現的做法

  最後可以看到對於每一個phase都調用了doPhase方法同時把LifeCycle和FacesContext當做參數傳入了值得注意的是所謂的phaseListener也傳入了phase的doPhase方法中由此大約能夠想明白這個階段監聽器的道理了


From:http://tw.wingwit.com/Article/program/Java/hx/201311/25717.html
    Copyright © 2005-2022 電腦知識網 Computer Knowledge   All rights reserved.