攔截器的使用
轉自http://blog.csdn.net/woshisap/article/details/7271854
1:攔截器(Interceptor)
攔截器是Struts2最強大的特性之一,它是一種可以讓用戶在Action執行之前和Result執行之后進行一些功能處理的機制。
圖中示意了三個攔截器,Interceptor1、Interceptor2、Interceptor3,注意的是他們的執行順序,在Action運行之前是按照Interceptor1、Inteceptor2和Inteceptor3的順序,而在Result執行之后,再次運行攔截器的時候是按照Interceptor3、Interceptor2和Interceptor1的順序執行的,順序剛好相反。
2:攔截器的優點
a:簡化了Action的實現。攔截器能把很多功能從Action中獨立出來,大量減少了Action的代碼
b:功能更單一。按照上面的描述,把功能從Action中分離出來,分散到不同的攔截器中,這樣每個攔截器的功能,以及Action本身的功能就更單一了。
c:通用代碼模塊化。從Action中把功能分離出來,放到攔截器中去實現,這樣能把一些在多個Action中通用的代碼進行模塊化,封裝在一個或者幾個攔截器中。
d:提高重用性。當通用的功能代碼被封裝在攔截器中,實現了代碼模塊化過程之后,就可以對不同的Action,根據功能需要,來配置相同的攔截器了。
e:實現AOP。
攔截器相比Filter具有更強大的功能,比如攔截器與Servlet的API無關,比如攔截器可以訪問到值棧等。
3:攔截器的的調用順序
a:首先,要找到它自己有沒有聲明攔截器的引用,即<action>元素有沒有<interceptor-ref>子元素,如果有,則不用繼續尋找,直接使用這些攔截器,如果沒有進行下一步的查找。
b:其次,找到這個<action>所在包有沒有聲明默認的攔截器引用,即<package>元素的<default-interceptor-ref>子元素,如果有,則不用繼續再找,直接使用這些攔截器,如果沒有,則進行下一步的查找。
c:遞歸的查找這個包的父包,看看有沒有聲明默認的攔截器引用,直到找到默認的攔截器引用為止。
4:開發自定義的攔截器
開發自定義的攔截器,要實現Interceptor接口,還要使用到ActionInvocation接口,現在對ActionInvocation接口進行簡單的介紹。
它里面有一些方法,如下:
a:getAction,獲得這次請求准備執行的Action對象。
b:getProxy,返回這次請求的ActionProxy對象,可以在這個對象上獲得要運行Action的哪個方法。
c:getInvocationContext,返回這個Action執行的上下文(ActionContext),可以在這個上下文對象中獲得大量的數據,比如請求的parameter值,session的值等。
d:在ActionContext中取到的parameter值是一個Map<String, Object>,其中以String為key,以String[]為value,這個Map記錄了所有的request參數。
e:getResult方法,返回Result運行之后代表結果的Result對象。
我們要實現這樣一個Aciton,要求攔截器輸出如下的信息:運行哪個Action類,運行哪個方法,請求的參數和Action運行完要跳轉到哪個JSP。
- import java.util.Map;
- import org.apache.struts2.dispatcher.ServletDispatcherResult;
- import com.opensymphony.xwork2.ActionInvocation;
- import com.opensymphony.xwork2.Result;
- import com.opensymphony.xwork2.interceptor.Interceptor;
- public class LoggerInterceptor implements Interceptor {
- @Override
- public void destroy() {
- }
- @Override
- public void init() {
- }
- @Override
- public String intercept(ActionInvocation invocation) throws Exception {
- System.out.println("-----begin------");
- //運行的action的名字
- String actionName = invocation.getAction().getClass().getName();
- System.out.println("Action:" + actionName);
- //執行的action的方法
- String method = invocation.getProxy().getMethod();
- System.out.println("method:" + method);
- //獲得這次請求的parameter對象,並打印
- Map<String, Object> params = invocation.getInvocationContext().getParameters();
- for(String key : params.keySet()) {
- Object obj = params.get(key);
- if(obj instanceof String[]) {
- String[] array = (String[])obj;
- System.out.print("Param: " + key + "values: ");
- for(String value : array) {
- System.out.print(value + ", ") ;
- }
- System.out.print("\n");
- }
- }
- //運行后續的攔截器、Action和Result
- String resultCode = invocation.invoke();
- //在Action和Result運行之后,得到Result對象,並且可以強制轉換成ServletDispatcherResult
- //打印其下一個jsp的位置
- Result result = invocation.getResult();
- if(result instanceof ServletDispatcherResult) {
- ServletDispatcherResult dispatcherResult = (ServletDispatcherResult)result;
- System.out.println("JSP:" + dispatcherResult.getLastFinalLocation());
- }
- System.out.println("-----end-----");
- return resultCode;
- }
- }
5:一個重要的攔截器timer
timer攔截器是Struts2的預定義攔截器之一,可以用來記錄Action運行的時間。
配置:在struts.xml中寫入配置信息,如下所示,
- <package name="hello" namespace="/" extends="struts-default">
- <interceptors>
- <interceptor name="MyLogger" class="com.capinfotech.inteceptor.LoggerInterceptor">
- </interceptor>
- </interceptors>
- <action name="hello" class="com.capinfotech.action.HelloAction">
- <interceptor-ref name="MyLogger"></interceptor-ref>
- <interceptor-ref name="timer"></interceptor-ref>
- <interceptor-ref name="defaultStack"></interceptor-ref>
- <result name="success">/WEB-INF/jsp/success.jsp</result>
- </action>
- </package>
程序運行輸入信息如下:
6:Struts2的預定義攔截器
a:params攔截器
把請求參數設置進Action的相應屬性,並自動進行類型轉換
b:staticParams攔截器
將struts.xml配置文件里定義的Action參數,設置到對應的Action實例中,Action參數使用<param>標簽,是<action>標簽的子元素。
<action name="hello" class="HelloAction">
<param name="account">test</param>
</action>
這要求action中有一個account屬性,並有相應的setter和getter方法,運行的時候,action的account屬性在初始化過后,會接到這里的賦值test。
c:prepare攔截器
在action執行之前調用Action的prepare方法,這個方法是用來准備action之前要做的工作,它要求用戶必須實現com.opensymphony.xwork2.Preparable接口。
d:modelDriven攔截器
如果action實現了ModelDriven接口,它將getModel方法取得的模型對象存入OgnlValueStack中。
e:chain攔截器
chain攔截器,將前一個執行結束的Action屬性設置到當前的action中,它被用在ResultType為"chain"所指定的結果的Action中,該結果Action對象會從值棧獲得前一個Action對應的屬性,它實現Action鏈之間的數據傳遞。
f:exception攔截器
在拋出異常的時候,這個攔截器起作用,任何應用都應該引用這個攔截器,而且引用的時候,最好把它放在第一位,讓它能捕獲所有的異常。
g:validation攔截器
調用驗證框架讀取*-validation.xml文件,並且應用在這些文件中聲明的校驗。
h:token攔截器
核對當前Action請求(request)的有效標識,防止重復提交Action請求,使用標簽<s:token>可以生成表單令牌,該標簽會在Session中設置一個預期的值,並且在表單中創建一個隱藏的input字段,Token攔截器會檢查這個令牌,如果不合法,將不會執行Action,這個攔截器是手工添加的,還需要一個invalide.token的result。
i:conversionError攔截器
用來處理框架進行類型轉化(Type Conversion)時的出錯信息,它將存儲在ActionContext中的類型轉化錯誤信息轉化成相應的Action字段的錯誤信息,保存在堆棧中。根據需要,可以將這些錯誤信息在視圖中顯示出來。
j:fileUpload攔截器
用來處理上傳文件
k:workflow攔截器
Action默認的工作流,如果Action實現了Validateable接口,那么interceptor會調用action的validate()方法,如果Action實現了ValidateAware接口,那么interceptor將會檢查Action是否包含錯誤信息,如果包含錯誤信息,那么Interceptor將會返回input,而不讓Action繼續執行。
l:servletConfig攔截器
這個攔截器提供Action直接對Servlet API的調用,把Servlet API的對象注入到Action中,包括ServletRequestAware,ServletResponseAware,ParameterAware,SessionAware和ApplicationAware
m:timer攔截器
記錄ActionInvocation剩余部分執行的時間,並作為日志信息記錄下來,便於尋找性能瓶頸。
n:logger攔截器
在日志信息中輸出要執行的Action信息,這樣,在調試的時候,就能很快的定位到這個對應的Action中了。
o:tokenSession攔截器
擴展了token攔截器的功能,當提交無效的Action請求標識時,它會跳轉到第一次成功后的頁面