Struts2的拦截器

拦截器(Interceptor)Struts2的核心组成部分。很多功能(Feature)是构建在拦截器基础上的,例如文件的上传和下载、国际化、转换器和数据校验等,Struts2利用内建的拦截器,完成了框架内的大部分操作。

拦截器动态拦截Action调用的对象,它提供了一种机制,使开发者可以定义一个特定的功能模块,这个模块可以在Action执行之前或者执行之后运行,也可以在一个Action执行之前阻止Action执行。同时也提供了一种可以提取Action中可重用的部分的方式。

Struts2架构中,可以使用配置文件,灵活配置定义拦截器。当需要一个拦截器的时候,只要在配置文件中设置即可;如果不需要时,可以取消该拦截器,这样就可以实现拦截器同Action类的松耦合,提高系统扩展性。

 

 

一、 Struts2拦截器原理

 

 

 

 

 Struts2架构的Action被一个或者多个拦截器(拦截器栈)所包围,所有的用户请求都会被拦截器所拦截,然后交给Action处理,处理结果以逻辑视图方式返回给用户。 这个调用执行流程是由Struts2的配置文件来实现的。 当用户请求到达Struts2ServletDispatcher时,Struts2会查找配置文件,并根据其配置实例化相对的拦截对象,然后串成一个列表(List),最后一个一个地调用列表中的拦截器。

 

二、 定义拦截器

 

     Struts2框架的拦截器处理机制采用了AOP(面向方面编程)设计思想。使得拦截器(拦截器组)可以类似“热插拔”的方式来组合,配合业务控制器Action来完成用户请求的处理。 这种“热插拔”实际上是通过Struts2框架的配置文件来实现的,配置文件中可以定义拦截器和拦截器栈,并可以在Action中定义所使用的拦截器或者拦截器栈。开发者如果要改变拦截器的执行顺序或者数量,只需要修改配置文件即可。

     struts.xml配置文件中,配置拦截器如下:

 

<interceptors>

   <!—定义拦截器-->

          <interceptor  class="intercept.FilterInterceptor"  

                  name="filterIntercept"></interceptor>

          <interceptor class="interceptOrder.InterceptorOrder"

                   name="InterceptorOrder">

           <!—定义拦截器参数-->

           <param name="">value</param>

           <param name="">value</param>

</interceptor>

          <interceptor name="checkIntercept" 

                class="authorityIntercept.CheckInterceptor">

</interceptor>

 <!—定义拦截器栈-->

          <interceptor-stack name="myDefaultStack">

                       <interceptor-ref name="defaultStack"></interceptor-ref>

                       <interceptor-ref name="checkIntercept"></interceptor-ref>

          </interceptor-stack>

       </interceptors>

 

三、 使用拦截器

 

     1、在Struts2框架中定义了拦截器或者拦截器栈,就可以在配置文件中使用该拦截器或者拦截器栈来拦截Action。指定拦截器或者拦截器栈,会在Actionexecute()方法执行之前被执行。 Action中配置拦截器如下:

  <action name="FilterAction" class="intercept.FilterAction">

                     <result name="success">/intercept/MethodFilter.jsp</result>

                        <!—显式引用默认拦截器-->

                     <interceptor-ref name="defaultStack"></interceptor-ref>  

                        <!—自定义拦截器栈-->

                     <interceptor-ref name="myDefaultStack">

                     </interceptorref>           

                     <interceptor-ref name="filterIntercept">

                        <!—在使用拦截器时指定拦截器参数-->

                            <param name="includeMethods">method1</param>

                            <param name="excludeMethods">method2</param>

                            <param name="name">方法过滤拦截器</param>

                     </interceptor-ref>         

              </action>

 

           注意:Struts2框架的默认拦截器defaultStack包含了很多重要的功能,在Action

             义自己的拦截器的同时,一定要注意需要同时显式的引用系统默认拦截器

                    defaultStack

 

     2 配置默认拦截器

 

         为了避免每个Action配置相同的拦截器,使用默认拦截器,则包内所有Action都会自动使用默认拦截器,避免了配置代码的重复使用。

         配置默认拦截器使用<default-interceptor-ref…/>元素,该元素为包<package…/>的一个子元素,如果在包配置中定义了一个默认拦截器,那么该拦截器对包内所有的Action都是有效的,Action中显式定义拦截器情况下除外。

<default-interceptor-ref…/>元素需要指定一个name属性,该属性指定默认拦截器的名称。该属性必须是一个已经存在的拦截器名称,即前面已经定义好了的。

<interceptors>

         <interceptor name="checkInterceptor" class="bbs.checkInterceptor">

         </interceptor>

         <interceptor-stack name="bbsStack">

            <interceptor-ref name="defaultStack"></interceptor-ref>

            <interceptor-ref name="checkInterceptor" />

            <interceptor-ref name="jsfStack" />

         </interceptor-stack>

</interceptors>

<!—指定包内默认拦截器-->

 <default-interceptor-ref name="bbsStack"></default-interceptor-ref>

 

注意:在指定包内默认拦截器时,只能使用一个<default-interceptor-ref…/>元素,即

      每个包内只能定义一个默认的拦截器。 如果需要将多个拦截器都设置为一个包的默

      认拦截器,最好的方式是将这些拦截器组成一个拦截器栈,再将拦截器栈设置为包

      的默认拦截器。

 

  3 自定义拦截器实现类

 

      1 Struts2框架为开发者自定义拦截器实现类提供了一个Interceptor接口,用户可

        以实现该接口来开发自定义拦截器实现类。Interceptor接口中定义了三个方法:

            init()destroy()String interceptor(ActionInvocation invocation)

 

      2 Struts2框架除了提供Interceptor接口用于开发自定义拦截器实现类外,还提供

        了一个com.opensymphony.xwork.interceptor.AbstractInterceptor 类,

        开发者只要继承该类,就可以用简单的方式来实现自己的拦截器实现类。该类实

        现了Interceptor接口。 该类同样定义了上面的三个方法,如果在用户自定义的

        拦截器实现类的初始化时,不需要加载一些特殊的系统资源,可以不用实现init()

        和destroy()方法。只需要重写interceptor(ActionInvocation invocation)

        法即可。

 

 

四、 拦截器深度剖析

 

     1 拦截器的方法过滤

 

         业务控制器Action中可以使用动态方法来处理用户请求,这样Struts2框架的Action更 

      加灵活。 Action中使用拦截器,默认情况下会拦截Action实现类中的所有方法。但

      是某些情况下,开发者可能只需要拦截Action中的一个或者多个方法,有时候也希望拦

      截器不拦截某些Action方法。 这时,让拦截器有选择的拦截Action中的某个方法,就

      需要使用拦截器的方法过滤。

 

  Struts2框架提供了一个MethodFilterInterceptor类,开发者自定义的拦截器只要继承

 该类,就可以使用拦截器的方法过滤功能,来拦截Action中特定的方法。

MethodFilterInterceptor类为

com.opensymphony.xwork.interceptor.AbstractInterceptor拦截器类的子类,实现

InterceptorSerializable接口。该类有两个重要的参数:

excludeMethods:该参数指定拦截器拒绝拦截的方法列表。多个方法值中间用逗号分开。

includeMethods: 该参数指定拦截器需要拦截的方法列表。多个方法值中间用逗号分开。

 

下面给出该类的主要方法:

  protected abstract String doInterceptor(ActionInvocation invocation) :继承该类的子类必须重写该方法,并实现拦截器逻辑。

  String interceptor(ActionInvocation invocation):继承自AbstractInterceptor类,该方法不需要强制重写。

  void setExcludeMethods(String excludeMethods):设置黑名单,该方法参数为一个字符

串,即对应的Action方法名称。

      void setIncludeMethods(String includeMethods):设置拦截器的白名单。

      Set getExcludeMethodsSet():获得拦截器的黑名单。

      Set getIncludeMethodsSet(): 获得拦截器的白名单。

   注意: 开发者使用MethodFilterInterceptor类的子类来实现拦截器的方法过滤,只需要

         重写doInterceptor(ActionInvocation invocation)方法即可。

  下面为实现方法过滤拦截的配置文件: filterInterceptor过滤器继承了MethodFilterInterceptor类。

    <interceptor-ref name="filterIntercept">

                <!—使用方法过滤,设置白名单或黑名单-->

               <param name="includeMethods">method1</param>

               <param name="excludeMethods">method2</param>

               <param name="name">方法过滤拦截器</param>

       </interceptor-ref>  

 

2 拦截器的执行顺序

     配置在前面的拦截器,会在被拦截方法执行之前执行拦截动作,拦截器的拦截动作是按照配置文件拦截器的引用顺序来执行的。

3 拦截结果监听器

    开发者如果需要在Action执行之后,拦截器的interceptor(ActionInvocation arg0)返回result之前进行一些业务处理操作。例如Action执行execute()后,返回一个“success”字符串,拦截器对该返回结果进行处理,修改某些业务数据后,再返回“success”逻辑视图。

1、    实现上面的要求,可以在拦截器的invoke()方法之后加入处理代码。例如:

    public String intercept(ActionInvocation arg0) throws Exception {

              //注册一个监听器

            arg0.addPreResultListener(new MyListener());

            System.out.println(name+"拦截器信息:启动拦截器,拦截Action

                            间:"+new Date());

            String result=arg0.invoke();

        //根据处理结果处理其他业务

        if(result.equals("success")){

             dosomething();

}

         System.out.println(name+"拦截器信息:Action执行完毕时间:"+new

Date());

              return result;

       }

 

2、    上面代码会导致拦截器中加入了大量的业务逻辑判断和处理代码,从而降低了系统代码的复用性。 为了处理Action执行处理方法之后和拦截器返回result之间节点的业务,Struts2框架提供了一个PreResultListener接口。实现该接口就可以监听Action特定方法执行之后的结果,并做进一步的预后处理。

 

PreResultListener接口中只有一个方法,如下所示。该方法中有两个参数,其中resultcode就是Action执行之后返回的结果。

 void beforeResult(ActionInvocation invocation, String resultcode)

 

1. 开发者可以开发自己的监听器类,该类必须实现PreResultListener接口,并重写void beforeResult(ActionInvocation invocation, String resultcode)方法。例如下面的代码:

   public class MyListener implements PreResultListener {

         public void beforeResult(ActionInvocation arg0, String arg1) {

              // TODO Auto-generated method stub

              System.out.println("监听器监听执行结果..."+arg1);

        }

}

 

2. 为了使用监听器,需要在拦截器中注册监听器。下面的示例中在拦截器中加入了监听器:

   public String intercept(ActionInvocation arg0) throws Exception {

        //注册一个监听器

        arg0.addPreResultListener(new MyListener());

System.out.println(name+"拦截器信息:启动拦截器,拦截Action时间:"+new Date());

String result=arg0.invoke();

System.out.println(name+"拦截器信息:Action执行完毕时间:"+new Date());

return result;

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值