转自http://blog.csdn.net/qjyong/article/details/1824607
++YONG 原创,转载请注明
拦截器,在 AOP ( Aspect-Oriented Programming )中用于在某个方法或字段被访问之前,进行拦截然后在之前或之后加入某些操作。拦截是 AOP 的一种实现策略。
在 Webwork 的中文文档的解释为——拦截器是动态拦截 Action 调用的对象。它提供了一种机制可以使开发者可以定义在一个 action 执行的前后执行的代码,也可以在一个 action 执行前阻止其执行。同时也是提供了一种可以提取 action 中可重用的部分的方式。
谈到拦截器,还有一个词大家应该知道——拦截器链( Interceptor Chain ,在 Struts 2 中称为拦截器栈 Interceptor Stack )。拦截器链就是将拦截器按一定的顺序联结成一条链。在访问被拦截的方法或字段时,拦截器链中的拦截器就会按其之前定义的顺序被调用。
大部分时候,拦截器方法都是通过代理的方式来调用的。 Struts 2 的拦截器实现相对简单。当请求到达 Struts 2 的 ServletDispatcher 时, Struts 2 会查找配置文件,并根据其配置实例化相对的拦截器对象,然后串成一个列表( list ),最后一个一个地调用列表中的拦截器。如下图:
Struts 2 已经为您提供丰富多样的,功能齐全的拦截器实现。大家可以至 struts2 的 jar 包内的 struts-default.xml 查看关于默认的拦截器与拦截器链的配置。
Struts2 ( XWork )提供的拦截器的功能说明:
拦截器 |
名字 |
说明 |
Alias Interceptor |
alias |
在不同请求之间将请求参数在不同名字件转换,请求内容不变 |
Chaining Interceptor |
chain |
让前一个 Action 的属性可以被后一个 Action 访问,现在和 chain 类型的 result ( <result type=”chain”> )结合使用。 |
Checkbox Interceptor |
checkbox |
添加了 checkbox 自动处理代码,将没有选中的 checkbox 的内容设定为 false ,而 html 默认情况下不提交没有选中的 checkbox 。 |
Cookies Interceptor |
cookies |
使用配置的 name,value 来是指 cookies |
Conversion Error Interceptor |
conversionError |
将错误从 ActionContext 中添加到 Action 的属性字段中。 |
Create Session Interceptor |
createSession |
自动的创建 HttpSession ,用来为需要使用到 HttpSession 的拦截器服务。 |
Debugging Interceptor |
debugging |
提供不同的调试用的页面来展现内部的数据状况。 |
Execute and Wait Interceptor |
execAndWait |
在后台执行 Action ,同时将用户带到一个中间的等待页面。 |
Exception Interceptor |
exception |
将异常定位到一个画面 |
File Upload Interceptor |
fileUpload |
提供文件上传功能 |
I18n Interceptor |
i18n |
记录用户选择的 locale |
Logger Interceptor |
logger |
输出 Action 的名字 |
Message Store Interceptor |
store |
存储或者访问实现 ValidationAware 接口的 Action 类出现的消息,错误,字段错误等。 |
Model Driven Interceptor |
model-driven |
如果一个类实现了 ModelDriven ,将 getModel 得到的结果放在 Value Stack 中。 |
Scoped Model Driven |
scoped-model-driven |
如果一个 Action 实现了 ScopedModelDriven ,则这个拦截器会从相应的 Scope 中取出 model 调用 Action 的 setModel 方法将其放入 Action 内部。 |
Parameters Interceptor |
params |
将请求中的参数设置到 Action 中去。 |
Prepare Interceptor |
prepare |
如果 Acton 实现了 Preparable ,则该拦截器调用 Action 类的 prepare 方法。 |
Scope Interceptor |
scope |
将 Action 状态存入 session 和 application 的简单方法。 |
Servlet Config Interceptor |
servletConfig |
提供访问 HttpServletRequest 和 HttpServletResponse 的方法,以 Map 的方式访问。 |
Static Parameters Interceptor |
staticParams |
从 struts.xml 文件中将 <action> 中的 <param> 中的内容设置到对应的 Action 中。 |
Roles Interceptor |
roles |
确定用户是否具有 JAAS 指定的 Role ,否则不予执行。 |
Timer Interceptor |
timer |
输出 Action 执行的时间 |
Token Interceptor |
token |
通过 Token 来避免双击 |
Token Session Interceptor |
tokenSession |
和 Token Interceptor 一样,不过双击的时候把请求的数据存储在 Session 中 |
Validation Interceptor |
validation |
使用 action-validation.xml 文件中定义的内容校验提交的数据。 |
Workflow Interceptor |
workflow |
调用 Action 的 validate 方法,一旦有错误返回,重新定位到 INPUT 画面 |
Parameter Filter Interceptor |
N/A |
从参数列表中删除不必要的参数 |
Profiling Interceptor |
profiling |
通过参数激活 profile |
在 struts.xml 文件中定义拦截器,拦截器栈:
< package name = "my" extends = "struts-default" namespace = "/manage" > < interceptors > <!-- 定义拦截器 --> < interceptor name = " 拦截器名 " class = " 拦截器实现类 " /> <!-- 定义拦截器栈 --> < interceptor-stack name = " 拦截器栈名 " > < interceptor-ref name = " 拦截器一 " /> < interceptor-ref name = " 拦截器二 " /> </ interceptor-stack > </ interceptors > ...... </package> |
一旦定义了拦截器和拦截器栈后,就可以使用这个拦截器或拦截器栈来拦截 Action 了。拦截器的拦截行为将会在 Action 的 exceute 方法执行之前被执行。
< action name = "userOpt" class = "org.qiujy.web.struts2.action.UserAction" > < result name = "success" > /success.jsp </ result > < result name = "error" > /error.jsp </ result > <!-- 使用拦截器 , 一般配置在 result 之后, --> <!-- 引用系统默认的拦截器 --> < interceptor-ref name = "defaultStack" /> < interceptor-ref name = " 拦截器名或拦截器栈名 " /> </ action > |
此处需要注意的是,如果为 Action 指定了一个拦截器,则系统默认的拦截器栈将会失去作用。为了继续使用默认拦截器,所以上面配置文件中手动引入了默认拦截器。
作为“框架( framework )”,可扩展性是不可或缺的。虽然, Struts 2 为我们提供如此丰富的拦截器实现,但是这并不意味我们失去创建自定义拦截器的能力,恰恰相反,在 Struts 2 自定义拦截器是相当容易的一件事。
所有的 Struts 2 的拦截器都直接或间接实现接口 com.opensymphony.xwork2.interceptor.Interceptor 。该接口提供了三个方法:
1) void init(); 在该拦截器被初始化之后,在该拦截器执行拦截之前,系统回调该方法。对于每个拦截器而言,此方法只执行一次。
2) void destroy(); 该方法跟 init() 方法对应。在拦截器实例被销毁之前,系统将回调该方法。
3) String intercept(ActionInvocation invocation) throws Exception; 该方法是用户需要实现的拦截动作。该方法会返回一个字符串作为逻辑视图。
除此之外,继承类 com.opensymphony.xwork2.interceptor.AbstractInterceptor 是更简单的一种实现拦截器类的方式,因为此类提供了 init() 和 destroy() 方法的空实现,这样我们只需要实现 intercept 方法。
两个步骤:
l 通过 <interceptor …> 元素来定义拦截器。
l 通过 <interceptor-ref …> 元素来使用拦截器。
使用自定义拦截器来完成用户权限的控制:当浏览者需要请求执行某个操作时,应用需要先检查浏览者是否登录,以及是否有足够的权限来执行该操作。
AuthorizationInterceptor.java
package org.qiujy.common;
import java.util.Map;
import com.opensymphony.xwork2.Action; import com.opensymphony.xwork2.ActionInvocation; import com.opensymphony.xwork2.interceptor.AbstractInterceptor;
/** * 权限检查拦截器 * * @author qiujy * @version 1.0 */ public class AuthorizationInterceptor extends AbstractInterceptor {
/* * 拦截 Action 处理的拦截方法 * */ public String intercept(ActionInvocation invocation) throws Exception {
Map session = invocation.getInvocationContext().getSession(); String userName = (String) session.get( "userName" );
if ( null != userName && userName.equals( "test" )) { System. out .println( " 拦截器:合法用户登录 ---" ); return invocation.invoke(); } else { System. out .println( " 拦截器:用户未登录 ---" ); return Action. LOGIN ; } } } |
struts.xml :
<! DOCTYPE struts PUBLIC "-//Apache Software Foundation//DTD Struts Configuration 2.0//EN" "http://struts.apache.org/dtds/struts-2.0.dtd" > < struts > < package name = "my" extends = "struts-default" >
< interceptors > <!-- 定义权限控制拦截器 --> < interceptor name = "authority" class = "org.qiujy.common.AuthorizationInterceptor" /> </ interceptors >
<!-- 定义全局处理结果 --> < global-results > <!-- 逻辑名为 login 的结果,映射到 /login.jsp 页面 --> < result name = "login" > /login.jsp </ result > </ global-results >
< action name = "listall" class = "org.qiujy.web.struts2.action.UserAction" method = "listAllUser" > < result name = "success" > /listall.jsp </ result > <!-- 使用拦截器 --> < interceptor-ref name = "defaultStack" /> < interceptor-ref name = "authority" /> </ action >
< action name = "userOpt" class = "org.qiujy.web.struts2.action.UserAction" > < result name = "success" > /success.jsp </ result > </ action > </ package > </ struts > |
其它页面见源代码。
在浏览器地址栏直接输入 http://localhost:8080/AuthorityInterceptorDemo/listall.action 来访问,此动作配置了权限拦截器,所有被转到登录页面。
登录后:
再访问 http://localhost:8080/AuthorityInterceptorDemo/listall.action 这个链接:
如果为了简化 struts.xml 文件的配置,避免在每个 Action 重复配置该拦截器,可以将拦截器配置成了一个默认拦截器栈。如下:
<! DOCTYPE struts PUBLIC "-//Apache Software Foundation//DTD Struts Configuration 2.0//EN" "http://struts.apache.org/dtds/struts-2.0.dtd" > < struts > < package name = "my" extends = "struts-default" >
< interceptors > <!-- 定义权限控制拦截器 --> < interceptor name = "authority" class = "org.qiujy.common.AuthorizationInterceptor" /> <!-- 定义一个包含权限控制的拦截器栈 --> < interceptor-stack name = "mydefault" > < interceptor-ref name = "defaultStack" /> < interceptor-ref name = "authority" /> </ interceptor-stack > </ interceptors >
<!-- 定义默认拦截器 --> < default-interceptor-ref name = "mydefault" />
<!-- 定义全局处理结果 --> < global-results > <!-- 逻辑名为 login 的结果,映射到 /login.jsp 页面 --> < result name = "login" > /login.jsp </ result > </ global-results >
< action name = "listall" class = "org.qiujy.web.struts2.action.UserAction" method = "listAllUser" > < result name = "success" > /listall.jsp </ result > </ action > </ package >
< package name = "font" extends = "struts-default" > < action name = "userOpt" class = "org.qiujy.web.struts2.action.UserAction" > < result name = "success" > /success.jsp </ result > </ action > </ package > </ struts > |
一旦在某个包下定义了默认拦截器栈,在该包下的所有 action 都会使用此拦截器栈。对于那些不想使用些拦截器栈的 action ,则应该将它放置在其它的包下。