攔截器(Interceptor)配置
上節簡單地介紹了Action的配置,這節簡單介紹一下攔截器的配置。
1 攔截器棧的配置
顧名思義,攔截器就是在action的執行前後實行攔截,加入某些操作。攔截器類似於servlet的過濾器。它們是按照定義的順序依次執行的。每一個攔截器訪問的都是相同的ActionInvocation,就像每個過濾器訪問的都是同一個Request。攔截器是通過攔截器棧進行組織的,攔截器棧組織了一系列的攔截器的集合。
查看struts-default.xml文件的struts-default包,可以看到有兩個元素<interceptors>和<interceptor-stack>。
<interceptors>元素:定義攔截器的名字和類
<interceptor-stack>元素:將特定的攔截器和攔截器棧組織在一起(攔截器棧中可以包含攔截器棧)
在struts-default.xml文件中已經定義了一些攔截器:
<interceptorname ="alias"class="com.opensymphony.xwork2.interceptor.AliasInterceptor"/>
<interceptorname ="autowiring"class="com.opensymphony.xwork2.spring.interceptor.ActionAutowiringInterceptor"/>
<interceptorname ="chain"class="com.opensymphony.xwork2.interceptor.ChainingInterceptor"/>
<interceptorname ="conversionError"class="org.apache.struts2.interceptor.StrutsConversionErrorInterceptor"/>
<interceptorname ="createSession"class="org.apache.struts2.interceptor.CreateSessionInterceptor"/>
<interceptorname ="debugging"class ="org.apache.struts2.interceptor.debugging.DebuggingInterceptor"/>
<interceptorname ="external-ref"class="com.opensymphony.xwork2.interceptor.ExternalReferencesInterceptor"/>
<interceptorname ="execAndWait"class="org.apache.struts2.interceptor.ExecuteAndWaitInterceptor"/>
<interceptorname ="exception"class="com.opensymphony.xwork2.interceptor.ExceptionMappingInterceptor"/>
<interceptorname ="fileUpload"class="org.apache.struts2.interceptor.FileUploadInterceptor"/>
<interceptorname ="i18n"class ="com.opensymphony.xwork2.interceptor.I18nInterceptor"/>
<interceptorname ="logger"class="com.opensymphony.xwork2.interceptor.LoggingInterceptor"/>
<interceptorname ="model-driven"class="com.opensymphony.xwork2.interceptor.ModelDrivenInterceptor"/>
<interceptorname ="scoped-model-driven"class="com.opensymphony.xwork2.interceptor.ScopedModelDrivenInterceptor"/>
<interceptorname ="params"class="com.opensymphony.xwork2.interceptor.ParametersInterceptor"/>
<interceptorname ="prepare"class ="com.opensymphony.xwork2.interceptor.PrepareInterceptor"/>
<interceptorname ="static-params"class="com.opensymphony.xwork2.interceptor.StaticParametersInterceptor"/>
<interceptorname ="scope"class="org.apache.struts2.interceptor.ScopeInterceptor"/>
<interceptorname ="servlet-config"class="org.apache.struts2.interceptor.ServletConfigInterceptor"/>
<interceptorname ="sessionAutowiring"class="org.apache.struts2.spring.interceptor.SessionContextAutowiringInterceptor"/>
<interceptorname ="timer"class="com.opensymphony.xwork2.interceptor.TimerInterceptor"/>
<interceptorname ="token"class="org.apache.struts2.interceptor.TokenInterceptor"/>
<interceptorname ="token-session"class="org.apache.struts2.interceptor.TokenSessionStoreInterceptor"/>
<interceptorname ="validation"class="com.opensymphony.xwork2.validator.ValidationInterceptor"/>
<interceptorname ="workflow"class="com.opensymphony.xwork2.interceptor.DefaultWorkflowInterceptor"/>
<interceptorname ="store"class="org.apache.struts2.interceptor.MessageStoreInterceptor"/>
<interceptorname ="checkbox"class="org.apache.struts2.interceptor.CheckboxInterceptor"/>
<interceptorname ="profiling"class="org.apache.struts2.interceptor.ProfilingActivationInterceptor"/>
每個攔截器的定義包含了一個唯一的名字和攔截器類的全名(具體包名和類名)。
在struts-default.xm中已經配置了以上的攔截器。如果您想要使用上述攔截器,只需要在應用程序struts.xml文件中通過“<include file="struts-default.xml" />”將struts-default.xml文件包含進來,並繼承其中的struts-default包(package),最後在定義Action時,使用“<interceptor-ref name="xx" />”引用攔截器或攔截器棧(interceptor stack)。一旦您繼承了struts-default包(package),所有Action都會調用攔截器棧——defaultStack。當然,在Action配置中加入“<interceptor-refname="xx" />”可以覆蓋defaultStack。
注:一旦在action中聲明瞭任何一個攔截器,就得聲明所有這個action要引用的攔截器,因爲默認攔截器已經被覆蓋了。
Struts2提供的攔截器功能說明:
攔截器 | 名字 | 說明 |
Alias Interceptor | alias | 在不同請求之間將請求參數在不同名字件轉換,請求內容不變 |
Chaining Interceptor | chain | 讓前一個Action的屬性可以被後一個Action訪問,現在和chain類型的result(<result type=”chain”>)結合使用。 |
Checkbox Interceptor | checkbox | 添加了checkbox自動處理代碼,將沒有選中的checkbox的內容設定爲false,而html默認情況下不提交沒有選中的checkbox。 |
Cookies Interceptor | cookies | 使用配置的name,value來是指cookies |
Conversion Error Interceptor | conversionError | 將錯誤從ActionContext中添加到Action的屬性字段中。 |
Create Session Interceptor | createSession | 自動的創建HttpSession,用來爲需要使用到HttpSession的攔截器服務。 |
Debugging Interceptor | debugging | 提供不同的調試用的頁面來展現內部的數據狀況。 |
Execute and Wait Interceptor | execAndWait | 在後臺執行Action,同時將用戶帶到一箇中間的等待頁面。 |
Exception Interceptor | exception | 將異常定位到一個畫面 |
File Upload Interceptor | fileUpload | 提供文件上傳功能 |
I18n Interceptor | i18n | 記錄用戶選擇的locale |
Logger Interceptor | logger | 輸出Action的名字 |
Message Store Interceptor | store | 存儲或者訪問實現ValidationAware接口的Action類出現的消息,錯誤,字段錯誤等。 |
Model Driven Interceptor | model-driven | 如果一個類實現了ModelDriven,將getModel得到的結果放在Value Stack中。 |
Scoped Model Driven | scoped-model-driven | 如果一個Action實現了ScopedModelDriven,則這個攔截器會從相應的Scope中取出model調用Action的setModel方法將其放入Action內部。 |
Parameters Interceptor | params | 將請求中的參數設置到Action中去。 |
Prepare Interceptor | prepare | 如果Acton實現了Preparable,則該攔截器調用Action類的prepare方法。 |
Scope Interceptor | scope | 將Action狀態存入session和application的簡單方法。 |
Servlet Config Interceptor | servletConfig | 提供訪問HttpServletRequest和HttpServletResponse的方法,以Map的方式訪問。 |
Static Parameters Interceptor | staticParams | 從struts.xml文件中將<action>中的<param>中的內容設置到對應的Action中。 |
Roles Interceptor | roles | 確定用戶是否具有JAAS指定的Role,否則不予執行。 |
Timer Interceptor | timer | 輸出Action執行的時間 |
Token Interceptor | token | 通過Token來避免雙擊 |
Token Session Interceptor | tokenSession | 和Token Interceptor一樣,不過雙擊的時候把請求的數據存儲在Session中 |
Validation Interceptor | validation | 使用action-validation.xml文件中定義的內容校驗提交的數據。 |
Workflow Interceptor | workflow | 調用Action的validate方法,一旦有錯誤返回,重新定位到INPUT畫面 |
Parameter Filter Interceptor | N/A | 從參數列表中刪除不必要的參數 |
Profiling Interceptor | profiling | 通過參數激活profile |
攔截器棧組織了一系類攔截器,例如,Struts 2 定義了一個名位basicStack的攔截器棧:
<interceptor-stackname="basicStack">
<interceptor-refname="exception"/>
<interceptor-refname="servletConfig"/>
<interceptor-refname="prepare"/>
<interceptor-refname="checkbox"/>
<interceptor-refname="params"/>
<interceptor-refname="conversionError"/>
</interceptor-stack>
<interceptor-ref>是用來引用特定的攔截器或攔截器棧。
在validationWorkflowStack的定義中就引用了攔截器棧basicStack。
<interceptor-stackname="validationWorkflowStack">
<interceptor-refname="basicStack"/>
<interceptor-refname="validation"/>
<interceptor-refname="workflow"/>
</interceptor-stack>
2 攔截器的配置
攔截器可以通過<param>元素來配置參數。例如,我們可以看到validation的驗證可以跳過某一個action的input()方法(對input()方法不執行驗證)。配置如下:
<interceptor-stackname="validationWorkflowStack">
...
<interceptor-refname="validation">
<paramname="excludeMethods">
input,back,cancel,browse
</param>
</interceptor-ref>
...
這是因爲validation攔截器是MethodFilterInterceptor的子類,MethodFilterInterceptor定義了一個excludeMethods的參數(還有includeMethods參數)。這個參數是以逗號分隔符解析出一系列不進行攔截的方法名的。以上的配置就是對input,back,cancel,browse等方法不進行攔截驗證。
假設已經定義了一個攔截器棧defaultStack並且該攔截器棧包含了validation攔截器,而且我們有一個action要用到defaultStack攔截器棧,但是它有一個方法doNotValidate()不需要進行validation驗證,怎麼辦呢?
也許你會這樣配置:
<actionname="errorConfiguration"class="com.stuqbx.web.action.ErrorAction">
<interceptor-refname="validation">
<paramname="excludeMethods">
input,back,cancel,browse,doNotValidate
</param>
</interceptor-ref>
</action>
但是,這樣配置運行之後,會發現其他的攔截器不起作用了,如前面所說的,action中一旦聲明瞭攔截器,就得把要用到 攔截器都聲明瞭。爲此,可能要把defaultStack中所有的攔截器都在聲明一遍,這太麻煩了。其實,我們還可以這樣:
<actionname="correctConfiguration"class="com.stuqbx.web.action.CorrectAction">
<interceptor-refname="defaultStack">
<paramname="validation.excludeMethods">
input,back,cancel,browse,doNotValidate
</param>
</interceptor-ref>
</action>
這配置了一個action,該action用到了defaultStack攔截器棧,並且爲其中的validation攔截器的excludeMethods參數配置了相應的值。配置的語法很簡單,用interceptorName.parameterName作爲param的name。還有如果在action中用到了一個攔截器棧,這個攔截器棧中又引用了多個攔截器棧,也可以爲其中的某些攔截器配置相應的參數,語法爲:stackName.interceptorName.parameterName。
3 默認攔截器
在package中可以用<default-interceptor-ref>來定義默認的攔截器。例如,在struts-default包中就定義了默認的攔截器:
<packagename="struts-default"abstract="true">
<!-- ... -->
<default-interceptor-refname="defaultStack"/>
</package>
4 攔截器工作原理
所有的Struts 2的攔截器都直接或間接實現接口com.opensymphony.xwork2.interceptor.Interceptor。該接口提供了三個方法:
void init(); 在該攔截器被初始化之後,在該攔截器執行攔截之前,系統回調該方法。對於每個攔截器而言,此方法只執行一次。
void destroy();該方法跟init()方法對應。在攔截器實例被銷燬之前,系統將回調該方法。
String intercept(ActionInvocation invocation) throws Exception; 該方法是用戶需要實現的攔截動作。該方法會返回一個字符串作爲邏輯視圖。
除此之外,繼承類com.opensymphony.xwork2.interceptor.AbstractInterceptor是更簡單的一種實現攔截器類的方式,因爲此類提供了init()和destroy()方法的空實現,這樣我們只需要實現intercept方法。
有些攔截器處理是跟action的調用無關的,有些攔截器只有在action實現了某些特定的接口時才執行。ActionInvocation有一個action的屬性,存儲了被調用的action的了實例。通過用instanceof檢查是被調用的action是哪一個,攔截器就可以決定是否攔截處理。
在自定義攔截器時,攔截器必須是無狀態的,不要使用在API提供的ActionInvocation之外的任何東西。攔截器是無狀態的是因爲Struts 2不能保證爲每一個請求或者action創建一個攔截器的實例,所以如果攔截器帶有狀態,會引發併發問題。