1. 程式人生 > >Struts2攔截器的一些使用方法

Struts2攔截器的一些使用方法

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中寫入配置資訊,如下所示,


<span style="font-size:14px;">    <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></span>

程式執行輸入資訊如下:

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請求標識時,它會跳轉到第一次成功後的頁面