WebWork教程- Interceptor(攔截器)
Interceptor
(攔截器)將
Action
共用的行為獨(dú)立出來,在
Action
執(zhí)行前后運(yùn)行。這也就是我們所說的
AOP
(
Aspect Oriented Programming
,面向切面編程),它是分散關(guān)注的編程方法,它將通用需求功能從不相關(guān)類之中分離出來;同時(shí),能夠使得很多類共享一個(gè)行為,一旦行為發(fā)生變化,不必修改很多類,只要修改這個(gè)行為就可以。
?
Interceptor
將很多功能從我們的
Action
中獨(dú)立出來,大量減少了我們
Action
的代碼,獨(dú)立出來的行為具有很好的重用性。
XWork
、
WebWork
的許多功能都是有
Interceptor
實(shí)現(xiàn),可以在配置文件中組裝
Action
用到的
Interceptor
,它會(huì)按照你指定的順序,在
Action
執(zhí)行前后運(yùn)行。
Interceptor
在框架中的應(yīng)用如下圖所示
?
?
當(dāng)你提交對(duì)
Aciton
(默認(rèn)是
.action
結(jié)尾的
Url
)的請(qǐng)求時(shí),
ServletDispatcher
會(huì)根據(jù)你的請(qǐng)求,去調(diào)度并執(zhí)行相應(yīng)的
Action
。在
Action
執(zhí)行之前,調(diào)用被
Interceptor
截取,
Interceptor
在
Action
執(zhí)行前后運(yùn)行。
?
我們?cè)谟脩糇?cè)的例子中就使用了取得
Request
請(qǐng)求參數(shù)的攔截器,配置文件中
<interceptor-ref name="params"/>
將攔截器
params
組裝到
RegisterAction
中?!?/span>
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>
這些都時(shí)有框架提供的默認(rèn)的
Interceptor
,下面我來看看
Interceptor
使用的步驟:
1、??
創(chuàng)建一個(gè)自己需要的
Interceptor
類,它必需實(shí)現(xiàn)
com.opensymphony.xwork.interceptor.Interceptor 接口,具體的開發(fā)見下面的 Interceptor 的原理。
com.opensymphony.xwork.interceptor.Interceptor 接口,具體的開發(fā)見下面的 Interceptor 的原理。
2、??
在配置文件(
xwork..xml
)中申明這個(gè)
Interceptor
類,它放在標(biāo)簽
<interceptor />
中,同是
<interceptor />
標(biāo)簽嵌入在
<interceptors />
標(biāo)簽內(nèi)部。
3、??
創(chuàng)建
Interceptor
棧,使用標(biāo)簽:
<interceptor-stack?/>
,
讓一組
Interceptor
可以按次序調(diào)用。(可選)
4、??
指定
Action
所要用到的
Interceptor
(前面申明過的),可以用
<interceptor-ref />
或
<default-interceptor-ref />
標(biāo)簽。前面的標(biāo)簽指定某個(gè)
Action
所用到的
Interceptor
,如果
Action
沒有被用
<interceptor-ref />
指定
Interceptor
,它將使用
<default-interceptor-ref />
指定的
Interceptor
。
框架中給我們提供了很多實(shí)用的
Interceptor
,它的定義上面已經(jīng)給出,它的具體功能如下:
l?????????
timer
:記錄
Action
執(zhí)行的時(shí)間,并做為日志信息輸出;
l?????????
logger
:在日志信息中輸出要執(zhí)行的
Action
信息;
l?????????
chain
:將前一個(gè)執(zhí)行結(jié)束的
Action
屬性設(shè)置到當(dāng)前的
Action
中。它被用在
ResultType
為“
chain
”指定結(jié)果的
Action
中,該結(jié)果
Action
對(duì)象會(huì)從
OgnlValueStack
中獲得前一個(gè)
Action
對(duì)應(yīng)的屬性,它實(shí)現(xiàn)
Action
鏈之間的數(shù)據(jù)傳遞;
l?????????
static-params
:將
xwork.xml
配置文件里定義的
Action
參數(shù),設(shè)置到對(duì)應(yīng)的
Action
中。
Action
參數(shù)使用
<param />
標(biāo)簽,是
<action />
標(biāo)簽的直接子元素。我們這里定義的
Action
類必需實(shí)現(xiàn)
com.opensymphony.xwork.config.entities
. Parameterizable
接口;
l?????????
params
:將
Request
請(qǐng)求的參數(shù)設(shè)置到相應(yīng)
Action
對(duì)象的屬性中,用戶注冊(cè)例子用到過這個(gè)攔截器;
l?????????
model-driven
:如果
Action
實(shí)現(xiàn)
ModelDriven
接口,它將
getModel()
取得的模型對(duì)象存入
OgnlValueStack
中;
l?????????
component
:激活組件功能支持,讓注冊(cè)過的組件在當(dāng)前
Action
中可用,即為
Action
提供
IoC
(依賴倒轉(zhuǎn)控制)框架的支持;
l?????????
token
:核對(duì)當(dāng)前
Action
請(qǐng)求(
request
)的有效標(biāo)識(shí),防止重復(fù)提交
Action
請(qǐng)求
(request)
。
l?????????
token-session
:功能同上,但是當(dāng)提交無效的
Action
請(qǐng)求標(biāo)識(shí)時(shí),它會(huì)將請(qǐng)求數(shù)據(jù)保存到
session
中。
l?????????
validation
:實(shí)現(xiàn)使用
xml
配置文件(
{Action}-validation.xml
)對(duì)
Action
屬性值進(jìn)行驗(yàn)證,詳細(xì)請(qǐng)看后面介紹的驗(yàn)證框架。
l?????????
workflow
:調(diào)用
Action
類的驗(yàn)證功能,假設(shè)
Action
使用
ValidationAware
實(shí)現(xiàn)驗(yàn)證(
ActionSupport
提供此功能),如果驗(yàn)證沒有通過,
workflow
會(huì)將請(qǐng)求返回到
input
視圖(
Action
的
<result />
中定義的)。
l?????????
servlet-config
:提供
Action
直接對(duì)
HttpServletRequest
或
HttpServletResponse
等
JavaServlet api
的訪問,
Action
要實(shí)現(xiàn)相應(yīng)的接口,例如:
ServletRequestAware
或
ServletResponseAware
等
。如果必需要提供對(duì)
JavaServlet api
的訪問,我們建議使用
ServletActionContext
,在前面
ActionContext
章節(jié)中有介紹。
l?????????
prepare
:在
Action
執(zhí)行之前調(diào)用
Action
的
prepare()
方法,這個(gè)方法是用來準(zhǔn)備
Action
執(zhí)行之前要做的工作。它要求我們的
Action
必需實(shí)現(xiàn)
com.opensymphony.xwork
. Preparable
接口
conversionError
:用來處理框架進(jìn)行類型轉(zhuǎn)化
(Type Conversion)
時(shí)的出錯(cuò)信息。它將存儲(chǔ)在
ActionContext
中的類型轉(zhuǎn)化(
Type Conversion
)錯(cuò)誤信息轉(zhuǎn)化成相應(yīng)的
Action
字段的錯(cuò)誤信息,保存在堆棧中。根據(jù)需要,可以將這些錯(cuò)誤信息在視圖中顯示出來。
?
Interceptor
的原理
下面我們來看看
Interceptor
是如何實(shí)現(xiàn)在
Action
執(zhí)行前后調(diào)用的:
Action
和
Interceptor
在框架中的執(zhí)行,是由
ActionInvocation
對(duì)象調(diào)用的。它是用方法:
String invoke() throws Exception;
來實(shí)現(xiàn)的,它首先會(huì)依次調(diào)用
Action
對(duì)應(yīng)的
Interceptor
,執(zhí)行完成所有的
Interceptor
之后,再去調(diào)用
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());
}
}
它會(huì)在攔截器棧中遍歷
Interceptor
,調(diào)用
Interceptor
的
方法:
String intercept(ActionInvocation invocation) throws Exception; 。
String intercept(ActionInvocation invocation) throws Exception; 。
我們一直都提到,
Interceptor
是在
Action
前后執(zhí)行,可是從上面的代碼我們看到的卻是執(zhí)行完所有
Interceptor
的
intercept
()
方法之后再去調(diào)用我們的
Action
。“在
Action
前后執(zhí)行”是如何實(shí)現(xiàn)的呢?我們來看看抽象類
AroundInterceptor
的
intercept
()
實(shí)現(xiàn):
public
String intercept(ActionInvocation invocation) throws Exception {
??????? String result = null;
?
??????? before(invocation);
??????? result = invocation.invoke();
??????? after(invocation, result);
?
??????? return result;
??? }
原來在
intercept
()
方法又對(duì)
ActionInvocation
的
invoke()
方法進(jìn)行遞歸調(diào)用,
ActionInvocation
循環(huán)嵌套在
intercept
()
中,一直到語句
result = invocation.invoke();
執(zhí)行結(jié)束,即:
Action
執(zhí)行完并返回結(jié)果
result
,這時(shí)
Interceptor
對(duì)象會(huì)按照剛開始執(zhí)行的逆向順序依次執(zhí)行結(jié)束。這樣
before
()
方法將在
Action
執(zhí)行前調(diào)用,
after
()
方法在
Action
執(zhí)行之后運(yùn)行
WebWork
教程
- Interceptor(
攔截器
)
Interceptor
(攔截器)將
Action
共用的行為獨(dú)立出來,在
Action
執(zhí)行前后運(yùn)行。這也就是我們所說的
AOP
(
Aspect Oriented Programming
,面向切面編程),它是分散關(guān)注的編程方法,它將通用需求功能從不相關(guān)類之中分離出來;同時(shí),能夠使得很多類共享一個(gè)行為,一旦行為發(fā)生變化,不必修改很多類,只要修改這個(gè)行為就可以。
?
Interceptor
將很多功能從我們的
Action
中獨(dú)立出來,大量減少了我們
Action
的代碼,獨(dú)立出來的行為具有很好的重用性。
XWork
、
WebWork
的許多功能都是有
Interceptor
實(shí)現(xiàn),可以在配置文件中組裝
Action
用到的
Interceptor
,它會(huì)按照你指定的順序,在
Action
執(zhí)行前后運(yùn)行。
Interceptor
在框架中的應(yīng)用如下圖所示
?
?
當(dāng)你提交對(duì)
Aciton
(默認(rèn)是
.action
結(jié)尾的
Url
)的請(qǐng)求時(shí),
ServletDispatcher
會(huì)根據(jù)你的請(qǐng)求,去調(diào)度并執(zhí)行相應(yīng)的
Action
。在
Action
執(zhí)行之前,調(diào)用被
Interceptor
截取,
Interceptor
在
Action
執(zhí)行前后運(yùn)行。
?
我們?cè)谟脩糇?cè)的例子中就使用了取得
Request
請(qǐng)求參數(shù)的攔截器,配置文件中
<interceptor-ref name="params"/>
將攔截器
params
組裝到
RegisterAction
中?!?/span>
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>
這些都時(shí)有框架提供的默認(rèn)的
Interceptor
,下面我來看看
Interceptor
使用的步驟:
1、??
創(chuàng)建一個(gè)自己需要的
Interceptor
類,它必需實(shí)現(xiàn)
com.opensymphony.xwork.interceptor.Interceptor 接口,具體的開發(fā)見下面的 Interceptor 的原理。
com.opensymphony.xwork.interceptor.Interceptor 接口,具體的開發(fā)見下面的 Interceptor 的原理。
2、??
在配置文件(
xwork..xml
)中申明這個(gè)
Interceptor
類,它放在標(biāo)簽
<interceptor />
中,同是
<interceptor />
標(biāo)簽嵌入在
<interceptors />
標(biāo)簽內(nèi)部。
3、??
創(chuàng)建
Interceptor
棧,使用標(biāo)簽:
<interceptor-stack?/>
,
讓一組
Interceptor
可以按次序調(diào)用。(可選)
4、??
指定
Action
所要用到的
Interceptor
(前面申明過的),可以用
<interceptor-ref />
或
<default-interceptor-ref />
標(biāo)簽。前面的標(biāo)簽指定某個(gè)
Action
所用到的
Interceptor
,如果
Action
沒有被用
<interceptor-ref />
指定
Interceptor
,它將使用
<default-interceptor-ref />
指定的
Interceptor
。
框架中給我們提供了很多實(shí)用的
Interceptor
,它的定義上面已經(jīng)給出,它的具體功能如下:
l?????????
timer
:記錄
Action
執(zhí)行的時(shí)間,并做為日志信息輸出;
l?????????
logger
:在日志信息中輸出要執(zhí)行的
Action
信息;
l?????????
chain
:將前一個(gè)執(zhí)行結(jié)束的
Action
屬性設(shè)置到當(dāng)前的
Action
中。它被用在
ResultType
為“
chain
”指定結(jié)果的
Action
中,該結(jié)果
Action
對(duì)象會(huì)從
OgnlValueStack
中獲得前一個(gè)
Action
對(duì)應(yīng)的屬性,它實(shí)現(xiàn)
Action
鏈之間的數(shù)據(jù)傳遞;
l?????????
static-params
:將
xwork.xml
配置文件里定義的
Action
參數(shù),設(shè)置到對(duì)應(yīng)的
Action
中。
Action
參數(shù)使用
<param />
標(biāo)簽,是
<action />
標(biāo)簽的直接子元素。我們這里定義的
Action
類必需實(shí)現(xiàn)
com.opensymphony.xwork.config.entities
. Parameterizable
接口;
l?????????
params
:將
Request
請(qǐng)求的參數(shù)設(shè)置到相應(yīng)
Action
對(duì)象的屬性中,用戶注冊(cè)例子用到過這個(gè)攔截器;
l?????????
model-driven
:如果
Action
實(shí)現(xiàn)
ModelDriven
接口,它將
getModel()
取得的模型對(duì)象存入
OgnlValueStack
中;
l?????????
component
:激活組件功能支持,讓注冊(cè)過的組件在當(dāng)前
Action
中可用,即為
Action
提供
IoC
(依賴倒轉(zhuǎn)控制)框架的支持;
l?????????
token
:核對(duì)當(dāng)前
Action
請(qǐng)求(
request
)的有效標(biāo)識(shí),防止重復(fù)提交
Action
請(qǐng)求
(request)
。
l?????????
token-session
:功能同上,但是當(dāng)提交無效的
Action
請(qǐng)求標(biāo)識(shí)時(shí),它會(huì)將請(qǐng)求數(shù)據(jù)保存到
session
中。
l?????????
validation
:實(shí)現(xiàn)使用
xml
配置文件(
{Action}-validation.xml
)對(duì)
Action
屬性值進(jìn)行驗(yàn)證,詳細(xì)請(qǐng)看后面介紹的驗(yàn)證框架。
l?????????
workflow
:調(diào)用
Action
類的驗(yàn)證功能,假設(shè)
Action
使用
ValidationAware
實(shí)現(xiàn)驗(yàn)證(
ActionSupport
提供此功能),如果驗(yàn)證沒有通過,
workflow
會(huì)將請(qǐng)求返回到
input
視圖(
Action
的
<result />
中定義的)。
l?????????
servlet-config
:提供
Action
直接對(duì)
HttpServletRequest
或
HttpServletResponse
等
JavaServlet api
的訪問,
Action
要實(shí)現(xiàn)相應(yīng)的接口,例如:
ServletRequestAware
或
ServletResponseAware
等
。如果必需要提供對(duì)
JavaServlet api
的訪問,我們建議使用
ServletActionContext
,在前面
ActionContext
章節(jié)中有介紹。
l?????????
prepare
:在
Action
執(zhí)行之前調(diào)用
Action
的
prepare()
方法,這個(gè)方法是用來準(zhǔn)備
Action
執(zhí)行之前要做的工作。它要求我們的
Action
必需實(shí)現(xiàn)
com.opensymphony.xwork
. Preparable
接口
conversionError
:用來處理框架進(jìn)行類型轉(zhuǎn)化
(Type Conversion)
時(shí)的出錯(cuò)信息。它將存儲(chǔ)在
ActionContext
中的類型轉(zhuǎn)化(
Type Conversion
)錯(cuò)誤信息轉(zhuǎn)化成相應(yīng)的
Action
字段的錯(cuò)誤信息,保存在堆棧中。根據(jù)需要,可以將這些錯(cuò)誤信息在視圖中顯示出來。
?
Interceptor
的原理
下面我們來看看
Interceptor
是如何實(shí)現(xiàn)在
Action
執(zhí)行前后調(diào)用的:
Action
和
Interceptor
在框架中的執(zhí)行,是由
ActionInvocation
對(duì)象調(diào)用的。它是用方法:
String invoke() throws Exception;
來實(shí)現(xiàn)的,它首先會(huì)依次調(diào)用
Action
對(duì)應(yīng)的
Interceptor
,執(zhí)行完成所有的
Interceptor
之后,再去調(diào)用
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());
}
}
它會(huì)在攔截器棧中遍歷
Interceptor
,調(diào)用
Interceptor
的
方法:
String intercept(ActionInvocation invocation) throws Exception; 。
String intercept(ActionInvocation invocation) throws Exception; 。
我們一直都提到,
Interceptor
是在
Action
前后執(zhí)行,可是從上面的代碼我們看到的卻是執(zhí)行完所有
Interceptor
的
intercept
()
方法之后再去調(diào)用我們的
Action
?!霸?/span>
Action
前后執(zhí)行”是如何實(shí)現(xiàn)的呢?我們來看看抽象類
AroundInterceptor
的
intercept
()
實(shí)現(xiàn):
public
String intercept(ActionInvocation invocation) throws Exception {
??????? String result = null;
?
??????? before(invocation);
??????? result = invocation.invoke();
??????? after(invocation, result);
?
??????? return result;
??? }
原來在
intercept
()
方法又對(duì)
ActionInvocation
的
invoke()
方法進(jìn)行遞歸調(diào)用,
ActionInvocation
循環(huán)嵌套在
intercept
()
中,一直到語句
result = invocation.invoke();
執(zhí)行結(jié)束,即:
Action
執(zhí)行完并返回結(jié)果
result
,這時(shí)
Interceptor
對(duì)象會(huì)按照剛開始執(zhí)行的逆向順序依次執(zhí)行結(jié)束。這樣
before
()
方法將在
Action
執(zhí)行前調(diào)用,
after
()
方法在
Action
執(zhí)行之后運(yùn)行
posted on 2006-09-01 13:39 Binary 閱讀(620) 評(píng)論(0) 編輯 收藏 所屬分類: Webwork