版本:
  Struts 2.0.14
 
問題描述:
  當開放 Struts2 的 Filter 能服務 INCLUDE 轉來的需求時,即
    <filter> 
        <filter-name>struts</filter-name>
        <filter-class>org.apache.struts2.dispatcher.FilterDispatcher</filter-class>
    </filter>
    <filter-mapping>
        <filter-name>struts</filter-name>
        <url-pattern>/*</url-pattern>
        <dispatcher>FORWARD</dispatcher>
        <dispatcher>REQUEST</dispatcher> 
        <dispatcher>ERROR</dispatcher>
        <dispatcher>INCLUDE</dispatcher> 
    </filter-mapping>
 
  此時,若在 JSP 的頁面上有任何與 include 相關的運作,如:<jsp:include>、<s:include> 甚至是 <tiles:insertAttribute>,則在之後若再使用任何一種 Struts2 的 Tag 時,都會導致ComponentTagSupport  類別內的 doStartTag() 方法中,取得 Container 的程式碼 (Dispatcher.getInstance().getContainer()) 丟出 NullPointerException。
 


問題追蹤:
  會讓 ComponentTagSupport 類別丟出 NullPointerException 的主因在 Dispatcher.getInstance() 時取出的物件為 null,而再進一步追查,發現 FilterDispatcher 的 doFilter() 方法的最後,一定會去執行 ActionContextCleanUp.cleanUp(req),而這個方法正是會將 Dispatcher 的 instance 清成 null,進而導致在 include 之後的 struts2 tag 會發生 NullPointerException 的問題。
 
  但仔細去看 ActionContextCleanUp.cleanUp() 方法,發現它有個例外機制可以避免將 Dispatcher 的 instance 清空,而啟動這個例外機制的方式,是將 ActionContextCleanUp 也加到 Filter 的行列,並且必需要加在 Struts2 的 Filter 之前。即:
    <filter>
        <filter-name>ActionContextCleanUp</filter-name>
        <filter-class>org.apache.struts2.dispatcher.ActionContextCleanUp</filter-class>
    </filter>
    <filter-mapping>
        <filter-name>ActionContextCleanUp</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>
    <filter> 
        <filter-name>struts</filter-name>
        <filter-class>org.apache.struts2.dispatcher.FilterDispatcher</filter-class>
    </filter>
    <filter-mapping>
        <filter-name>struts</filter-name>
        <url-pattern>/*</url-pattern>
        <dispatcher>FORWARD</dispatcher>
        <dispatcher>REQUEST</dispatcher> 
        <dispatcher>ERROR</dispatcher>
        <dispatcher>INCLUDE</dispatcher> 
    </filter-mapping>
 
後續的觀察:
  設定好之後使用 eclipse 的 debug 機制去觀察運作的結果,發現當 struts2 的 filter 被 <jsp:include> 觸發,在 doFilter() 最後呼叫 ActionContextCleanUp.cleanUp() 時,ActionContextCleanUp 的避免清除機制有被啟動,所以 Dispatcher 的 instance 沒被清成 null,因此在 <jsp:include> 之後的 struts2 tag 也不會發生 NullPointerException 的錯誤。
 
  即使在同一個 jsp 頁面上有多個 <jsp:include> 時也都會如此運作,但請放心的是,當整個 request 結束時 (也可以說主要的這個 action -> jsp 運作結束時),Dispatcher 的 instance 以及ActionContext 的 context 都確定能被清成 null。

arrow
arrow
    全站熱搜

    大笨鳥 發表在 痞客邦 留言(0) 人氣()