详解Struts2的拦截器机制

1.拦截器体系是Struts2框架的重要组成部分,可以把Struts2理解成一个空容器,而大量的内建拦截器完成了该框架的大部分操作。比如,params拦截器负责解析HTTP请求的参数,并设置Action的属性;Servlet-config拦截器直接将HTTP请求中的HttpServletRequst实例和HttpServletResponse实例传给Action;fileUpload拦截器则负责解析请求参数中的文件域,并将一个文件域设置成Action的3个属性...

Struts2拦截器是可插拔式的设计:如果我们需要使用某个拦截器时,只需要在配置文件中应用该拦截器即可;如果不需要就取消该拦截器。

Struts2拦截器由struts-default.xml、struts.xml等配置文件进行管理

对于任何MVC框架来说,它们都会完成一些通用的控制逻辑,例如解析请求参数,类型转换,将请求参数封装成DTO(Data Transfer Object),执行输入校验,解析文件上传表单中的文件域,防止表单的多次提交...

Struts2把大部分核心控制器需要完成的工作按功能分开定义,每个拦截器完成一个功能。而这些拦截器可以自用选择,灵活组合。

当FilterDispatcher拦截用户请求之后,大量拦截器将会对用户请求进行处理,然后才会调用用户开发的Action实例的方法来处理请求。

ServletDispacth初始化一个ActionProxy实例,并调用它的execute方法

拦截器方法会先拦截并处理用户请求,然后才到Action的execute方法处理用户请求

返回一个逻辑试图名,系统负责将该逻辑视图对应的资源显示给用户

 

2.Struts2内建的拦截器

Struts2内建了大量的拦截器,这些拦截器以name-class对的形式配置在struts-default.xml文件中,其中name是拦截器的名字,就是以后使用该拦截器的唯一标识;class则指定了该拦截器的实现类,如果我们定的package继承了Struts2的默认的struts-default包,则可使用默认的拦截器

内建拦截器简要介绍:

alias:实现在不同请求中相似参数别名的转换

autowiring:自动装配的拦截器,主要用于Struts2与Spring整合时,Struts2可以使用自动装配的方式访问Spring容器中的Bean

chain:构建一个Action链,使当前Action可以访问前一个Action的属性,一般和<result type="chain".../>一起使用

conversionError:负责处理类型转换错误的拦截器,负责将类型转换错误从ActionContext中取出,并转换成Action的FieldError错误

createSession:负责创建一个HttpSession对象,主要用于那些需要有HttpSession对象才能正常工作的拦截器

debugging:在开发模式下,会提供更多的调试信息

execAndWait:后台执行Action,负责将等待画面发送给用户

exception:负责处理异常信息,将异常映射为结果

fileUpload:用户文件上传,负责解析表单中文件域的内容

i18n:支持国际化的拦截器,负责把所选的语言、区域放入用户Session中

logger:负责日志记录的拦截器

model-driven:一个用于模型驱动的拦截器,当某个Action类实现了ModelDriven接口时,负责把getModel()方法的结果推入ValueStack中

scoped-model-driven:如果一个Action实现了一个SessionModelDriven接口,该拦截器负责从指定生存范围中找出指定的Model,并将通过setModel方法将该Model传给Action实例

params:负责解析HTTP请求中的参数,并将参数值设置成Action对应的属性值

prepare:如果Action实现了Preparable接口,将会调用该拦截器的prepare()方法

static-params:负责将xml中<action>标签下<param>标签中的参数传入action

scope:范围转换拦截器,可以将Action状态信息保存到HttpSession范围,或者保存到ServletContext范围内

servlet-config:如果某个Action需要直接访问Servlet API,就是通过这个拦截器实现

roles:JAAS拦截器

timer:负责输出Action的执行时间,在分析该Action的性能瓶颈时比较有用

token:防止重复提交,检查传到Action中的token,从而防止多次提交

token-session:把token放到HttpSession中

validation:通过执行在xxxAction-validation.xml中定义的校验器,从而完成数据校验

workflow:负责调用Action类中的validate方法,如果校验失败,返回input的逻辑试图

 

3.配置拦截器

<!-- 通过指定拦截器名和拦截器实现类来定义拦截器 -->

<interceptor name="拦截器名" class="拦截器实现类">

        <param name="参数名">参数值</param>

</interceptor>

<interceptor-stack name="拦截器栈名">

        <interceptor-ref name="拦截器一" />

        <interceptor-ref name="拦截器栈一" />

</interceptor-stack>

在Action中使用拦截器,应在result元素之后

配置默认拦截器

<default-interceptor-ref ... />

struts-default.xml中的默认配置

 

4.实现拦截器

开发自己的拦截器,应该实现com.opensymphony.xwork2.interceptor.Interceptor接口

public interface Interceptor extends Serializable{

      //销毁该拦截器之前的回调方法

      void destroy();

      //初始化该拦截器的回调方法

      void init();

      //拦截器实现拦截的逻辑方法

      String intercept(ActionInvocation invocation)throws Exception;

}

intercept方法返回一个字符串作为逻辑试图。如果该方法直接返回了一个字符串,系统将会跳转到该逻辑试图对应的实际试图资源,不会调用被拦截的Action。该方法的ActionInvocation参数包含了被拦截的Action的引用,可以通过调用该参数的invoke方法,将控制权转给下一个拦截器,或者转给Action的execute方法

如果为Action指定了一个拦截器,则系统默认的拦截器将会失去作用。为了继续使用默认拦截器,应在配置文件中手动应用默认拦截器

 

5.拦截方法的拦截器

为了实现方法过滤的特性,Struts2提供了一个MethodFilterInterceptor类,该类是AbstractInterceptor类的子类,提供了一个doIntercept(ActionInvocation invocation)抽象方法。实现方法过滤的拦截器需要继承MethodFilterInterceptor抽象类,并且重写doIntercept方法定义对Action的拦截逻辑

在MethodFilterInterceptor方法中,增加了如下两个方法:

public void setExcludeMethods(String excludeMethods);

public void setIncludeMethods(String includeMethods);

Struts2提供了这种方法拦截器有如下几个:

TokenInterceptor

TokenSessionStoreInterceptor

DefaultWorkflowInterceptor

ValidationInterceptor

 

6.拦截器的执行顺序

在Action的控制逻辑方法执行之前,位于拦截器链前面的拦截器将先发生作用;在Action的控制逻辑方法执行之后,位于拦截器前面的拦截器将后发生作用

 

7.拦截结果的监听器

为了精确定义在execute方法执行结束后,在处理物理资源转向之前的动作,Struts2提供了用于拦截结果的监听器。这个监听器是通过手动注册在拦截器内部的。实现拦截结果的监听器必须实现PreResultListener接口。

public class MyPreResultListener implements PreResultListener{

       //定义在处理Result之前的行为

       public void beforeResult(ActionInvocation invocation,String resultCode){

              System.out.println(resultCode);

       }

}

public class BeforeResultInterceptor extends AbstractInterceptor{

       public String intercept(ActionInvocation invocation) throws Exception{

              //将一个拦截结果的监听器注册给该拦截器

              invocation.addPreResultListener(new MyPreResultListener());

              String result = invocation.invoke();

              return result;

       }

}

 

8.使用拦截器完成权限检查

检查用户是否登录,通常都是通过跟踪用户的session来完成的,通过ActionContext即可访问到session中的属性,拦截器的intercept(ActionInvocation invocation)方法的invocation参数可以很轻易地访问到请求相关的ActionContext实例。

public class AuthorityInterceptor extends AbstraceInterceptor{

       public String intercept(ActionInvocation invocation) throws Exception{

              //取得请求相关的ActionContext实例

              ActionContext ctx = invocation.getInvocationContext();

              Map session = ctx.getSession();

              String user = (String)session.get("user");

              //判断

              return invocation.invoke();

       }

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值