Interceptor在Struts2中的應用...

Interceptor(攔截器)將Action共用的行爲獨立出來,在Action執行前後運行。這也就是我們所說的AOP(Aspect Oriented Programming,面向切面編程),它是分散關注的編程方法,它將通用需求功能從不相關類之中分離出來;同時,能夠使得很多類共享一個行爲,一旦行爲發生變化,不必修改很多類,只要修改這個行爲就可以。

Interceptor將很多功能從我們的Action中獨立出來,大量減少了我們Action的代碼,獨立出來的行爲具有很好的重用性。XWork、WebWork的許多功能都是有Interceptor實現,可以在配置文件中組裝Action用到的Interceptor,它會按照你指定的順序,在Action執行前後運行。Interceptor在框架中的應用如下圖所示:

interceptor webwork2 結構圖

當你提交對Aciton(默認是.action結尾的Url)的請求時,ServletDispatcher會根據你的請求,去調度並執行相應的Action。在Action執行之前,調用被 Interceptor截取,Interceptor在Action執行前後運行。

我們在用戶註冊的例子中就使用了取得Request請求參數的攔截器,配置文件中將攔截器params組裝到RegisterAction中。“params”在我們的webwork-default.xml配置文件中有定義,webwork-default.xml中攔截器的定義如下:

 

<interceptors>
    
<interceptor name="validation" class="com.opensymphony.xwork.validator.ValidationInterceptor"/>
    
<interceptor name="static-params" class="com.opensymphony.xwork.interceptor.StaticParametersInterceptor"/>
    
<interceptor name="params" class="com.opensymphony.xwork.interceptor.ParametersInterceptor"/> 
    
<interceptor name="conversionError" class="com.opensymphony.webwork.interceptor.WebWorkConversionErrorInterceptor"/> 
    
<interceptor-stack name="defaultStack">
        
<interceptor-ref name="static-params"/> 
        
<interceptor-ref name="params"/> 
        
<interceptor-ref name="conversionError"/> 
    
</interceptor-stack> 
</interceptors> 


這些都時有框架提供的默認的Interceptor,下面我來看看Interceptor使用的步驟:


1、  創建一個自己需要的Interceptor類,它必需實現com.opensymphony.xwork.interceptor.Interceptor接口,具體的開發見下面的Interceptor的原理。

2、  在配置文件(xwork..xml)中申明這個Interceptor類,它放在標籤中,同是標籤嵌入在標籤內部。

3、  創建Interceptor棧,使用標籤:  />,讓一組Interceptor可以按次序調用。(可選)

4、  指定Action所要用到的Interceptor(前面申明過的),可以用或標籤。前面的標籤指定某個Action所用到的Interceptor,如果Action沒有被用指定Interceptor,它將使用指定的Interceptor。


框架中給我們提供了很多實用的Interceptor,它的定義上面已經給出,它的具體功能如下:

● timer:記錄Action執行的時間,並做爲日誌信息輸出;

● logger:在日誌信息中輸出要執行的Action信息;

● chain:將前一個執行結束的Action屬性設置到當前的Action中。它被用在ResultType爲“chain”指定結果的Action中,該結果Action對象會從OgnlValueStack中獲得前一個Action對應的屬性,它實現Action鏈之間的數據傳遞;

● static-params:將xwork.xml配置文件裏定義的Action參數,設置到對應的Action中。Action參數使用標籤,是標籤的直接子元素。我們這裏定義的Action類必需實現com.opensymphony.xwork.config.entities. Parameterizable接口;

● params:將Request請求的參數設置到相應Action對象的屬性中,用戶註冊例子用到過這個攔截器;

● model-driven:如果Action實現ModelDriven接口,它將getModel()取得的模型對象存入OgnlValueStack中;

● component:激活組件功能支持,讓註冊過的組件在當前Action中可用,即爲Action提供IoC(依賴倒轉控制)框架的支持;

● token:覈對當前Action請求(request)的有效標識,防止重複提交Action請求(request)。

● token-session:功能同上,但是當提交無效的Action請求標識時,它會將請求數據保存到session中。

● validation:實現使用xml配置文件({Action}-validation.xml)對Action屬性值進行驗證,詳細請看後面介紹的驗證框架。

● workflow:調用Action類的驗證功能,假設Action使用ValidationAware實現驗證(ActionSupport提供此功能),如果驗證沒有通過,workflow會將請求返回到input視圖(Action的中定義的)。

● servlet-config:提供Action直接對HttpServletRequest或HttpServletResponse等JavaServlet api的訪問,Action要實現相應的接口,例如:ServletRequestAware或ServletResponseAware等。如果必需要提供對JavaServlet api的訪問,我們建議使用ServletActionContext,在前面ActionContext章節中有介紹。

● prepare:在Action執行之前調用Action的prepare()方法,這個方法是用來準備Action執行之前要做的工作。它要求我們的Action必需實現com.opensymphony.xwork. Preparable接口

● conversionError:用來處理框架進行類型轉化(Type Conversion)時的出錯信息。它將存儲在ActionContext中的類型轉化(Type Conversion)錯誤信息轉化成相應的Action字段的錯誤信息,保存在堆棧中。根據需要,可以將這些錯誤信息在視圖中顯示出來。

Interceptor的原理

下面我們來看看Interceptor是如何實現在Action執行前後調用的:

Action和Interceptor在框架中的執行,是由ActionInvocation對象調用的。它是用方法:String invoke() throws Exception;來實現的,它首先會依次調用Action對應的Interceptor,執行完成所有的Interceptor之後,再去調用Action的方法,代碼如下:

 

if (interceptors.hasNext()) ...{
 Interceptor interceptor 
= (Interceptor) interceptors.next();
 resultCode 
= interceptor.intercept(this);
}
 else ...{
    
if (proxy.getConfig().getMethodName() == null...{
        resultCode 
= getAction().execute();
    }
 else ...{
        resultCode 
= invokeAction(getAction(), proxy.getConfig());
    }

}

 

它會在攔截器棧中遍歷Interceptor,調用Interceptor的方法:
String intercept(ActionInvocation invocation) throws Exception;。

我們一直都提到,Interceptor是在Action前後執行,可是從上面的代碼我們看到的卻是執行完所有Interceptor的intercept()方法之後再去調用我們的Action。“在Action前後執行”是如何實現的呢?我們來看看抽象類AroundInterceptor的intercept()實現:

 

public String intercept(ActionInvocation invocation) throws Exception ...{
    String result 
= null;
    before(invocation);
    result 
= invocation.invoke();
    after(invocation, result);
    
return result;
}

 

原來在intercept()方法又對ActionInvocation的invoke()方法進行遞歸調用,ActionInvocation循環嵌套在intercept()中,一直到語句result = invocation.invoke();執行結束,即:Action執行完並返回結果result,這時Interceptor對象會按照剛開始執行的逆向順序依次執行結束。這樣before()方法將在Action執行前調用,after()方法在Action執行之後運行。

參考:

(1) webwork中的Interceptor http://www.blogchinese.com/06042/201878/archives/2006/200682171647.shtml
(2) Interceptor(攔截器)框架 http://hellboys.bokee.com/2093340.html

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章