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
的原理。
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
是如何实现在
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
执行之后运行
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
的原理。
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
是如何实现在
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
执行之后运行