拦截器是拦截Action,与servlet中的filter相似,主要采用配置方式(struts.xml)实现的。

一个拦截器要实现Interceptor接口,其中有三个方法:init, destroy, intercept.

MyInterceptor

 import com.opensymphony.xwork2.ActionInvocation;
 import com.opensymphony.xwork2.interceptor.Interceptor;

 public class MyInterceptor implements Interceptor
 {

     private String hello;
     
     public String getHello()
     {
         return hello;
     }

     public void setHello(String hello)
     {
         this.hello = hello;
     }

     public void destroy()
     {
         System.out.println("destroy");
     }

     public void init()
     {
         System.out.println("init");
         System.out.println(hello);
     }

     public String intercept(ActionInvocation invocation) throws Exception
     {
         System.out.println("intercept");
         
         String result = invocation.invoke();    //如果还有其它拦截器,则调用其它拦截器,若无,则调用Action
         
         System.out.println("finish");
         
         return result;
     }
 }


 struts.xml


定义拦截器

<interceptors>
     //配置自定义的拦截器
     <interceptor name="myInterceptor" class="com.test.interceptor.MyInterceptor">
             <param name="hello">world</param>    //对myInterceptor里面的hello属性赋初值
     </interceptor>
     <interceptor name="myInterceptor2" class="com.test.interceptor.MyInterceptor2">
             <param name="hello">world</param>    //对myInterceptor里面的hello属性赋初值
     </interceptor>
     <interceptor name="myInterceptor2" class="com.test.interceptor.MyInterceptor3">
     </interceptor>

     //配置一个拦截器栈
     <interceptor-stack name="myStack">
     <!-- 
         <interceptor-ref name="myInterceptor"></interceptor-ref>    //拦截器会按照此此配置顺序执行
         <interceptor-ref name="myInterceptor2"></interceptor-ref>
     -->
         <interceptor-ref name="defaultStack"></interceptor-ref>
     </interceptor-stack>
 </interceptors>



还可自定义默认的拦截器,以替换struts默认的拦截器。它会应用到所有的没配置拦截器的action中去。0或1个

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



拦截器对谁起作用

<action name="register" class="com.test.action.RegisterAction" method="test">
     <result name="success">/success.jsp</result>
         <param name="hello">welcome</param>        //对上面的初值时行了覆盖
     <result name="input">/register2.jsp</result>
     <!--


    或直接使用拦截器栈,拦截器栈还可引用拦截器栈。

<interceptor-ref name="myInterceptor"></interceptor-ref>
      -->
     <!--
     <interceptor-ref name="myInterceptor3">
         <param name="includeMethods">test, execute</param>    //表示拦截这两个方法
     </interceptor-ref>
     -->
     <interceptor-ref name="myInterceptor3">
         <param name="excludeMethods">test, execute</param>    //表示不拦截这两个方法
     </interceptor-ref>
     //或一个拦截器中同时含有includeMethods和excludeMethods,则includeMethods优先。
 </action>



本来在register提交时若发生错误,应回到自身页面,但配置了此拦截器,则会跳到success页面。
    多个拦截器可以构成一个拦截器栈。
因为在struts.xml中的<packge name="struts2" extends="struts-default">继承了struts-default.xml
struts-default.xml中已经定义好了许多的拦截器,并有一个默认的拦截器栈。
当我们在一个action中配置了一个自定义的拦截器栈后,struts-default.xml中的默认拦截器栈就不起作用了。
解决方法:手动的再将struts-default.xml中的默认拦截器栈导入。


大部分情况下,自定义的拦截器会extends AbstractInterceptor 而不去实现Interceptor
AbstractInterceptor实现了Interceptor,并重写了INterceptor中的init() 与 destory(),方法体什么都不做,
并且把intercept()重写为抽象的方法,让继承者去重写。因此extends AbstractInterceptor只须重写intercept()即可。

MyInterceptor2
 import com.opensymphony.xwork2.ActionInvocation;
 import com.opensymphony.xwork2.interceptor.AbstractInterceptor;
 public class MyInterceptor2 extends AbstractInterceptor {
     @Override
     public String intercept(ActionInvocation invocation) throws Exception {
         System.out.println("intercept2");    //执行目标之前做什么
         String result = invocation.invoke();    //执行下一个拦截器或action
         System.out.println("finish2");        //执行之后做什么
         return result;
     }
 }



拦截器的嵌套类似于(())的嵌套,出口顺序与入口顺序相反。



以上的拦截器是对action的拦截,即对action中的可调用方法都进行拦截。
而MethodFilterInterceptor可具体到action中的某个方法,更加细粒度。
它也继承了AbstractInterceptor,并将intercept()重写了,但intercept()中又调用了
抽象的doIntercept()因此,我们只要继承它并重写doIntercept()即可。

import com.opensymphony.xwork2.ActionInvocation;
 import com.opensymphony.xwork2.interceptor.MethodFilterInterceptor;
 public class MyInterceptor3 extends MethodFilterInterceptor {
     @Override
     public void init()     {
         System.out.println("init3");
     }
     @Override
     protected String doIntercept(ActionInvocation invocation) throws Exception {
         System.out.println("my interceptor3");
         String result = invocation.invoke();
         return result;
     }
 }