WebWork教程- Interceptor(攔截器)
WebWork教程- Interceptor(攔截器)
Interceptor(攔截器)將Action共用的行為獨立出來,在Action執行前后運行。這也就是我們所說的AOP(Aspect Oriented Programming,面向切面編程),它是分散關注的編程方法,它將通用需求功能從不相關類之中分離出來;同時,能夠使得很多類共享一個行為,一旦行為發生變化,不必修改很多類,只要修改這個行為就可以。
Interceptor將很多功能從我們的Action中獨立出來,大量減少了我們Action的代碼,獨立出來的行為具有很好的重用性。XWork、WebWork的許多功能都是有Interceptor實現,可以在配置文件中組裝Action用到的Interceptor,它會按照你指定的順序,在Action執行前后運行。Interceptor在框架中的應用如下圖所示
當你提交對Aciton(默認是.action結尾的Url)的請求時,ServletDispatcher會根據你的請求,去調度并執行相應的Action。在Action執行之前,調用被 Interceptor截取,Interceptor在Action執行前后運行。
我們在用戶注冊的例子中就使用了取得Request請求參數的攔截器,配置文件中<interceptor-ref name="params"/>將攔截器params組裝到RegisterAction中。“params”在我們的webwork-default.xml配置文件中有定義,webwork-default.xml中攔截器的定義如下:
<interceptors>
<interceptor name="timer" class="com.opensymphony.xwork.interceptor.TimerInterceptor"/>
<interceptor name="logger" class="com.opensymphony.xwork.interceptor.LoggingInterceptor"/>
<interceptor name="chain" class="com.opensymphony.xwork.interceptor.ChainingInterceptor"/>
<interceptor name="static-params" class="com.opensymphony.xwork.interceptor.StaticParametersInterceptor"/>
<interceptor name="params" class="com.opensymphony.xwork.interceptor.ParametersInterceptor"/>
<interceptor name="model-driven" class="com.opensymphony.xwork.interceptor.ModelDrivenInterceptor"/>
<interceptor name="component" class="com.opensymphony.xwork.interceptor.component.ComponentInterceptor"/>
<interceptor name="token" class="com.opensymphony.webwork.interceptor.TokenInterceptor"/>
<interceptor name="token-session" class="com.opensymphony.webwork.interceptor.TokenSessionStoreInterceptor"/>
<interceptor name="validation" class="com.opensymphony.xwork.validator.ValidationInterceptor"/>
<interceptor name="workflow" class="com.opensymphony.xwork.interceptor.DefaultWorkflowInterceptor"/>
<interceptor name="servlet-config" class="com.opensymphony.webwork.interceptor.ServletConfigInterceptor"/>
<interceptor name="prepare" class="com.opensymphony.xwork.interceptor.PrepareInterceptor"/>
<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>
<interceptor-stack name="validationWorkflowStack">
<interceptor-ref name="defaultStack"/>
<interceptor-ref name="validation"/>
<interceptor-ref name="workflow"/>
</interceptor-stack>
</interceptors>
這些都時有框架提供的默認的Interceptor,下面我來看看Interceptor使用的步驟:
1、 創建一個自己需要的Interceptor類,它必需實現
com.opensymphony.xwork.interceptor.Interceptor接口,具體的開發見下面的Interceptor的原理。
com.opensymphony.xwork.interceptor.Interceptor接口,具體的開發見下面的Interceptor的原理。
2、 在配置文件(xwork..xml)中申明這個Interceptor類,它放在標簽<interceptor />中,同是<interceptor />標簽嵌入在<interceptors />標簽內部。
3、 創建Interceptor棧,使用標簽:<interceptor-stack />,讓一組Interceptor可以按次序調用。(可選)
4、 指定Action所要用到的Interceptor(前面申明過的),可以用<interceptor-ref />或<default-interceptor-ref />標簽。前面的標簽指定某個Action所用到的Interceptor,如果Action沒有被用<interceptor-ref />指定Interceptor,它將使用<default-interceptor-ref />指定的Interceptor。
框架中給我們提供了很多實用的Interceptor,它的定義上面已經給出,它的具體功能如下:
l timer:記錄Action執行的時間,并做為日志信息輸出;
l logger:在日志信息中輸出要執行的Action信息;
l chain:將前一個執行結束的Action屬性設置到當前的Action中。它被用在ResultType為“chain”指定結果的Action中,該結果Action對象會從OgnlValueStack中獲得前一個Action對應的屬性,它實現Action鏈之間的數據傳遞;
l static-params:將xwork.xml配置文件里定義的Action參數,設置到對應的Action中。Action參數使用<param />標簽,是<action />標簽的直接子元素。我們這里定義的Action類必需實現com.opensymphony.xwork.config.entities. Parameterizable接口;
l params:將Request請求的參數設置到相應Action對象的屬性中,用戶注冊例子用到過這個攔截器;
l model-driven:如果Action實現ModelDriven接口,它將getModel()取得的模型對象存入OgnlValueStack中;
l component:激活組件功能支持,讓注冊過的組件在當前Action中可用,即為Action提供IoC(依賴倒轉控制)框架的支持;
l token:核對當前Action請求(request)的有效標識,防止重復提交Action請求(request)。
l token-session:功能同上,但是當提交無效的Action請求標識時,它會將請求數據保存到session中。
l validation:實現使用xml配置文件({Action}-validation.xml)對Action屬性值進行驗證,詳細請看后面介紹的驗證框架。
l workflow:調用Action類的驗證功能,假設Action使用ValidationAware實現驗證(ActionSupport提供此功能),如果驗證沒有通過,workflow會將請求返回到input視圖(Action的<result />中定義的)。
l servlet-config:提供Action直接對HttpServletRequest或HttpServletResponse等JavaServlet api的訪問,Action要實現相應的接口,例如:ServletRequestAware或ServletResponseAware等。如果必需要提供對JavaServlet api的訪問,我們建議使用ServletActionContext,在前面ActionContext章節中有介紹。
l 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;。
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執行之后運行
WebWork教程- Interceptor(攔截器)
Interceptor(攔截器)將Action共用的行為獨立出來,在Action執行前后運行。這也就是我們所說的AOP(Aspect Oriented Programming,面向切面編程),它是分散關注的編程方法,它將通用需求功能從不相關類之中分離出來;同時,能夠使得很多類共享一個行為,一旦行為發生變化,不必修改很多類,只要修改這個行為就可以。
Interceptor將很多功能從我們的Action中獨立出來,大量減少了我們Action的代碼,獨立出來的行為具有很好的重用性。XWork、WebWork的許多功能都是有Interceptor實現,可以在配置文件中組裝Action用到的Interceptor,它會按照你指定的順序,在Action執行前后運行。Interceptor在框架中的應用如下圖所示
當你提交對Aciton(默認是.action結尾的Url)的請求時,ServletDispatcher會根據你的請求,去調度并執行相應的Action。在Action執行之前,調用被 Interceptor截取,Interceptor在Action執行前后運行。
我們在用戶注冊的例子中就使用了取得Request請求參數的攔截器,配置文件中<interceptor-ref name="params"/>將攔截器params組裝到RegisterAction中。“params”在我們的webwork-default.xml配置文件中有定義,webwork-default.xml中攔截器的定義如下:
<interceptors>
<interceptor name="timer" class="com.opensymphony.xwork.interceptor.TimerInterceptor"/>
<interceptor name="logger" class="com.opensymphony.xwork.interceptor.LoggingInterceptor"/>
<interceptor name="chain" class="com.opensymphony.xwork.interceptor.ChainingInterceptor"/>
<interceptor name="static-params" class="com.opensymphony.xwork.interceptor.StaticParametersInterceptor"/>
<interceptor name="params" class="com.opensymphony.xwork.interceptor.ParametersInterceptor"/>
<interceptor name="model-driven" class="com.opensymphony.xwork.interceptor.ModelDrivenInterceptor"/>
<interceptor name="component" class="com.opensymphony.xwork.interceptor.component.ComponentInterceptor"/>
<interceptor name="token" class="com.opensymphony.webwork.interceptor.TokenInterceptor"/>
<interceptor name="token-session" class="com.opensymphony.webwork.interceptor.TokenSessionStoreInterceptor"/>
<interceptor name="validation" class="com.opensymphony.xwork.validator.ValidationInterceptor"/>
<interceptor name="workflow" class="com.opensymphony.xwork.interceptor.DefaultWorkflowInterceptor"/>
<interceptor name="servlet-config" class="com.opensymphony.webwork.interceptor.ServletConfigInterceptor"/>
<interceptor name="prepare" class="com.opensymphony.xwork.interceptor.PrepareInterceptor"/>
<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>
<interceptor-stack name="validationWorkflowStack">
<interceptor-ref name="defaultStack"/>
<interceptor-ref name="validation"/>
<interceptor-ref name="workflow"/>
</interceptor-stack>
</interceptors>
這些都時有框架提供的默認的Interceptor,下面我來看看Interceptor使用的步驟:
1、 創建一個自己需要的Interceptor類,它必需實現
com.opensymphony.xwork.interceptor.Interceptor接口,具體的開發見下面的Interceptor的原理。
com.opensymphony.xwork.interceptor.Interceptor接口,具體的開發見下面的Interceptor的原理。
2、 在配置文件(xwork..xml)中申明這個Interceptor類,它放在標簽<interceptor />中,同是<interceptor />標簽嵌入在<interceptors />標簽內部。
3、 創建Interceptor棧,使用標簽:<interceptor-stack />,讓一組Interceptor可以按次序調用。(可選)
4、 指定Action所要用到的Interceptor(前面申明過的),可以用<interceptor-ref />或<default-interceptor-ref />標簽。前面的標簽指定某個Action所用到的Interceptor,如果Action沒有被用<interceptor-ref />指定Interceptor,它將使用<default-interceptor-ref />指定的Interceptor。
框架中給我們提供了很多實用的Interceptor,它的定義上面已經給出,它的具體功能如下:
l timer:記錄Action執行的時間,并做為日志信息輸出;
l logger:在日志信息中輸出要執行的Action信息;
l chain:將前一個執行結束的Action屬性設置到當前的Action中。它被用在ResultType為“chain”指定結果的Action中,該結果Action對象會從OgnlValueStack中獲得前一個Action對應的屬性,它實現Action鏈之間的數據傳遞;
l static-params:將xwork.xml配置文件里定義的Action參數,設置到對應的Action中。Action參數使用<param />標簽,是<action />標簽的直接子元素。我們這里定義的Action類必需實現com.opensymphony.xwork.config.entities. Parameterizable接口;
l params:將Request請求的參數設置到相應Action對象的屬性中,用戶注冊例子用到過這個攔截器;
l model-driven:如果Action實現ModelDriven接口,它將getModel()取得的模型對象存入OgnlValueStack中;
l component:激活組件功能支持,讓注冊過的組件在當前Action中可用,即為Action提供IoC(依賴倒轉控制)框架的支持;
l token:核對當前Action請求(request)的有效標識,防止重復提交Action請求(request)。
l token-session:功能同上,但是當提交無效的Action請求標識時,它會將請求數據保存到session中。
l validation:實現使用xml配置文件({Action}-validation.xml)對Action屬性值進行驗證,詳細請看后面介紹的驗證框架。
l workflow:調用Action類的驗證功能,假設Action使用ValidationAware實現驗證(ActionSupport提供此功能),如果驗證沒有通過,workflow會將請求返回到input視圖(Action的<result />中定義的)。
l servlet-config:提供Action直接對HttpServletRequest或HttpServletResponse等JavaServlet api的訪問,Action要實現相應的接口,例如:ServletRequestAware或ServletResponseAware等。如果必需要提供對JavaServlet api的訪問,我們建議使用ServletActionContext,在前面ActionContext章節中有介紹。
l 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;。
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執行之后運行
posted on 2007-06-28 09:37 junky 閱讀(1407) 評論(1) 編輯 收藏 所屬分類: struts