+ 实现 Interceptor 接口
com.opensymphony.xwork2.interceptor.
Interceptor,接口定义如下:
public
interface
Interceptor
extends
Serializable {
void
destroy();
void
init();
String intercept(ActionInvocation invocation)
throws
Exception;
}
|
* init():主要在 interceptor 被创建后调用,主要用于初始化一些必要的资源,如:数据库资源等等;
* destroy():在 interceptor 实例被销毁前调用,主要用于释放一些分配的资源;
* intercept(ActionInvocation invocation):即为用户需要实现的拦截动作,输入参数为 ActionInvocation,其包含了被拦截的 Action 的引用,可以调用该参数的 invoke 方法,将控制权转给下一个拦截器,或者转给 Action 的 execute 方法;另外,该方法的返回参数是一个与 Action 的 execute 方法一样的 作为 逻辑视图 的字符串,如果该方法直接返回了一个字符串,则会跳转到 逻辑视图 对应 的 实际视图资源,而不会再调用被拦截 的 Action;
通过查看 Interceptor 的 Hierarchy,可以看到系统已经提供了很多的 Interceptor 类:
可以看到绝大部分的 Interceptor 实现类都是继承于 AbstractInterceptor 抽象类的,而该类的 init() 和 destroy() 方法提供的是一个空实现,因此,如果我们实现的拦截器不需要申请资源,则可以无需实现这两个方法。下面通过 LoggingInterceptor 的了解一下 interceptor 的基本实现方式:
public
class
LoggingInterceptor
extends
AbstractInterceptor {
private
static
final
Logger
LOG
= LoggerFactory.getLogger(LoggingInterceptor.
class
);
private
static
final
String
FINISH_MESSAGE
=
"Finishing execution stack for action "
;
private
static
final
String
START_MESSAGE
=
"Starting execution stack for action "
;
@Override
public
String intercept(ActionInvocation invocation)
throws
Exception {
logMessage(invocation,
START_MESSAGE
);
// 执行该拦截器的下一个拦截器,或者是 Action 的 execute 方法
String result = invocation.invoke();
logMessage(invocation,
FINISH_MESSAGE
);
return
result;
}
private
void
logMessage(ActionInvocation invocation, String baseMessage) {
if
(
LOG
.isInfoEnabled()) {
StringBuilder message =
new
StringBuilder(baseMessage);
String namespace = invocation.getProxy().getNamespace();
if
((namespace !=
null
) && (namespace.trim().length() > 0)) {
message.append(namespace).append(
"/"
);
}
message.append(invocation.getProxy().getActionName());
if
(
LOG
.isInfoEnabled()) {
LOG
.info(message.toString());
}
}
}
}
|
可以看到 LoggingInterceptor 只是简单的在 action 的执行之前和之后输出 INFO 级别的 start 和 finish 日志。
另外,如果需要在拦截器中解析 HTTP 请求或响应等信息,以及将解析的请求中的参数设置给 Action 的属性(其实这是系统 params 拦截器实现的功能),可通过 ServletActionContext 来获取 HTTP 请求或响应:
public
String intercept(ActionInvocation invocation)
throws
Exception {
HttpServletRequest request = ServletActionContext.getRequest();
HttpServletResponse response = ServletActionContext.getResponse();
String contentType = request.getHeader(
"content-type"
);
|
+ 使用拦截器
<
package
name
=
"cdsmc.auth"
extends
=
"struts-default"
>
<!-- 拦截器定义 -->
<
interceptors
>
<!-- 因当前 package 扩展于 struts-default,而在 struts-default.xml 中已经定义了 logger,因此这里使用了 logger-test -->
<
interceptor
name
=
"loggerTest"
class
=
"com.opensymphony.xwork2.interceptor.LoggingInterceptor"
/>
</
interceptors
>
<
action
name
=
"login"
class
=
"actionLogin"
>
<
result
name
=
"error"
type
=
"redirect"
>
/login.jsp
</
result
>
<
result
name
=
"success"
type
=
"redirect"
>
/user/list.jsp
</
result
>
<
interceptor-ref
name
=
"defaultStack"
/>
<
interceptor-ref
name
=
"loggerTest"
/>
</
action
>
</
package
>
|
定义了拦截器 loggerTest,并在 login action 中引用了该拦截器,另外,注意到在action中还显式的引用了 defaultStack 拦截器栈,这是因为如果在 action 中指定了一个拦截器,则系统默认的拦截器则会失效。而默认拦截器栈的作用可以参考下面的 struts-default.xml 中对于 defaultStack 的定义。
上面注释提到的,关于使用的 LoggingInterceptor 其实已经在 struts-default.xml 中定义了,而且我们上面看到的 Interceptor 继承结构中的Interceptor实现类都已经在此配置中定义,如下(strut2-core-2.3.4.1):
<
package
name
=
"struts-default"
abstract
=
"true"
>
...
<
interceptors
>
<
interceptor
name
=
"alias"
class
=
"com.opensymphony.xwork2.interceptor.AliasInterceptor"
/>
<
interceptor
name
=
"autowiring"
class
=
"com.opensymphony.xwork2.spring.interceptor.ActionAutowiringInterceptor"
/>
<
interceptor
name
=
"chain"
class
=
"com.opensymphony.xwork2.interceptor.ChainingInterceptor"
/>
......
<interceptor name = "logger" class= "com.opensymphony.xwork2.interceptor.LoggingInterceptor" />
<
interceptor
name
=
"modelDriven"
class
=
"com.opensymphony.xwork2.interceptor.ModelDrivenInterceptor"
/>
......
<
interceptor
name
=
"annotationWorkflow"
class
=
"com.opensymphony.xwork2.interceptor.annotations.AnnotationWorkflowInterceptor"
/>
<
interceptor
name
=
"multiselect"
class
=
"org.apache.struts2.interceptor.MultiselectInterceptor"
/>
......
<interceptor-stack name = "defaultStack">
<
interceptor-ref
name
=
"exception"
/>
<
interceptor-ref
name
=
"alias"
/>
<
interceptor-ref
name
=
"servletConfig"
/>
<
interceptor-ref
name
=
"i18n"
/>
<
interceptor-ref
name
=
"prepare"
/>
<
interceptor-ref
name
=
"chain"
/>
<
interceptor-ref
name
=
"scopedModelDriven"
/>
<
interceptor-ref
name
=
"modelDriven"
/>
<
interceptor-ref
name
=
"fileUpload"
/>
<
interceptor-ref
name
=
"checkbox"
/>
<
interceptor-ref
name
=
"multiselect"
/>
<
interceptor-ref
name
=
"staticParams"
/>
<
interceptor-ref
name
=
"actionMappingParams"
/>
<
interceptor-ref
name
=
"params"
>
<
param
name
=
"excludeParams"
>
dojo\..*,^struts\..*,^session\..*,^request\..*,^application\..*,^servlet(Request|Response)\..*,parameters\...*
</
param
>
</
interceptor-ref
>
<
interceptor-ref
name
=
"conversionError"
/>
<
interceptor-ref
name
=
"validation"
>
<
param
name
=
"excludeMethods"
>
input,back,cancel,browse
</
param
>
</
interceptor-ref
>
<
interceptor-ref
name
=
"workflow"
>
<
param
name
=
"excludeMethods"
>
input,back,cancel,browse
</
param
>
</
interceptor-ref
>
<
interceptor-ref
name
=
"debugging"
/>
</ interceptor-stack>
... ...
</
interceptors
>
<
default-interceptor-ref
name
=
"defaultStack"
/>
<
default-class-ref
class
=
"com.opensymphony.xwork2.ActionSupport"
/>
</
package
>
|
配置完成后测试运行,可看到如下日志:
2013-01-12 09:26:59|15715507@qtp-5480883-5|INFO|com.opensymphony.xwork2.interceptor.LoggingInterceptor|Starting execution stack for action //login
2013-01-12 09:26:59|15715507@qtp-5480883-5|DEBUG|com.opensymphony.xwork2.DefaultActionInvocation|Executing action method = null
2013-01-12 09:26:59|15715507@qtp-5480883-5|DEBUG|org.apache.struts2.dispatcher.ServletRedirectResult|Redirecting to finalLocation /cdsmc/user/list.jsp
2013-01-12 09:26:59|15715507@qtp-5480883-5|INFO|com.opensymphony.xwork2.interceptor.LoggingInterceptor|Finishing execution stack for action //login
|
转载于:https://blog.51cto.com/quietmadman/1116319