天天看點

Interceptor模式在Webwork2中的應用

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中攔截器的定義如下:

Interceptor模式在Webwork2中的應用

< interceptors >

Interceptor模式在Webwork2中的應用

     < interceptor  name ="validation"  class ="com.opensymphony.xwork.validator.ValidationInterceptor" />

Interceptor模式在Webwork2中的應用

     < interceptor  name ="static-params"  class ="com.opensymphony.xwork.interceptor.StaticParametersInterceptor" />

Interceptor模式在Webwork2中的應用

     < interceptor  name ="params"  class ="com.opensymphony.xwork.interceptor.ParametersInterceptor" />  

Interceptor模式在Webwork2中的應用

     < interceptor  name ="conversionError"  class ="com.opensymphony.webwork.interceptor.WebWorkConversionErrorInterceptor" />  

Interceptor模式在Webwork2中的應用

     < interceptor-stack  name ="defaultStack" >

Interceptor模式在Webwork2中的應用

         < interceptor-ref  name ="static-params" />  

Interceptor模式在Webwork2中的應用

         < interceptor-ref  name ="params" />  

Interceptor模式在Webwork2中的應用

         < interceptor-ref  name ="conversionError" />  

Interceptor模式在Webwork2中的應用

     </ interceptor-stack >  

Interceptor模式在Webwork2中的應用

</ 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的方法,代碼如下:

Interceptor模式在Webwork2中的應用
Interceptor模式在Webwork2中的應用

if  (interceptors.hasNext())  ... {

Interceptor模式在Webwork2中的應用

 Interceptor interceptor = (Interceptor) interceptors.next();

Interceptor模式在Webwork2中的應用

 resultCode = interceptor.intercept(this);

Interceptor模式在Webwork2中的應用
Interceptor模式在Webwork2中的應用

}   else   ... {

Interceptor模式在Webwork2中的應用
Interceptor模式在Webwork2中的應用

    if (proxy.getConfig().getMethodName() == null) ...{

Interceptor模式在Webwork2中的應用

        resultCode = getAction().execute();

Interceptor模式在Webwork2中的應用
Interceptor模式在Webwork2中的應用

    } else ...{

Interceptor模式在Webwork2中的應用

        resultCode = invokeAction(getAction(), proxy.getConfig());

Interceptor模式在Webwork2中的應用

    }

Interceptor模式在Webwork2中的應用

}

它會在攔截器棧中周遊Interceptor,調用Interceptor的方法:

String intercept(ActionInvocation invocation) throws Exception;。

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

Interceptor模式在Webwork2中的應用
Interceptor模式在Webwork2中的應用

public  String intercept(ActionInvocation invocation)  throws  Exception  ... {

Interceptor模式在Webwork2中的應用

    String result = null;

Interceptor模式在Webwork2中的應用

    before(invocation);

Interceptor模式在Webwork2中的應用

    result = invocation.invoke();

Interceptor模式在Webwork2中的應用

    after(invocation, result);

Interceptor模式在Webwork2中的應用

    return result;

Interceptor模式在Webwork2中的應用

}

原來在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

繼續閱讀