(转)Struts 拦截器

一、拦截器是怎么实现: 

实际上它是用Java中的动态代理来实现的 



二、拦截器在Struts2中的应用 
对于Struts2框架而言,正是大量的内置拦截器完成了大部分操作。像params拦截器将http请求中参数解析出来赋值给Action中对 应的属性。Servlet-config拦截器负责把请求中HttpServletRequest实例和HttpServletResponse实例传递 给Action……struts2内置的拦截器有很多,在此我就不一一列举了。 

那么怎么在struts2中定义自己的拦截器呢? 

很简单Struts2为我们提供了一个Interceptor接口,该接口源代码如下: 

publicinterface Interceptor extends Serializable { 

    void destroy(); 

    void init(); 

    String intercept(ActionInvocation invocation) throws Exception; 



1)    init():在拦截器执行之前调用,主要用于初始化系统资源。 

2)    destroty():与init()对应,用于拦截器执行之后销毁资源。 

3)    intercept():拦截器的核心方法,实现具体的拦截操作。与action一样,该方法也返回一个字符串作为逻辑视图。如果拦截器成功调用了 action,则返回一个真正的,也就是该action中execute()方法返回的逻辑视图,反之,则返回一个自定义的逻辑视图。 

通常我们使用拦截器并不需要申请资源,为此Struts2还为我们提供了一个AbstractInterceptor类,该类的init()和destroy()都是空实现。我们开发自己的拦截器只需要继承这个类就行了。 

下面创建一个判断用户是否登录的拦截器。代码如下: 

import java.util.Map; 
import com.opensymphony.xwork2.Action; 
import com.opensymphony.xwork2.ActionInvocation; 
import com.opensymphony.xwork2.interceptor.AbstractInterceptor; 

@SuppressWarnings("serial") 
public class CheckLoginInterceptor extends AbstractInterceptor { 

    @SuppressWarnings("unchecked") 
    public String intercept(ActionInvocation actionInvocation) throws Exception { 
         System.out.println("begin check login interceptor!"); 

            // 检查Session中是否存在user 

            Map session = actionInvocation.getInvocationContext().getSession(); 

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

            if (username != null && username.length() > 0) { 

                // 存在的情况下进行后续操作。 

                System.out.println("already login!"); 

                return actionInvocation.invoke(); 

            } else { 

                // 否则终止后续操作,返回LOGIN 

                System.out.println("no login, forward login page!"); 

                return Action.LOGIN; 

            } 
        } 
    } 


创建好拦截器后,还不能使用,还需要我们在struts.xml中配置一下。 

下面看一下怎么配置拦截器。 

<interceptors> 

           <interceptor name="checkLogin" class="com.myblog.interceptor.CheckLoginInterceptor" /> 

</interceptors> 

这个定义好的拦截器在Action中怎么使用呢?使用方法很简单,如下: 

<action name=" " class=" " > 

           <result> </result> 

           <interceptor-ref name="checkLogin" /> 

</action> 

一旦我们为某个action引用了自定义的拦截器,struts2默认的拦截器就不会再起作用,因此还需要引用默认拦截器。 

<action name=" " class=" " > 

           <result> </result> 

           <interceptor-ref name="checkLogin" /> 

                     <interceptor-ref name="defaultStack" /> 

</action> 

但是我们这么做似乎也不太方便,因为如果拦截器checkLogin需要被多个action引用的话,每一个都要配置一遍太麻烦了。我们可以把它定义成默认的拦截器。 

<interceptors> 

           <interceptor name="checkLogin" class="com.myblog.interceptor.CheckLoginInterceptor" /> 

           <!—-定义一个拦截器栈--> 
           <interceptor-stack name="mydefault"> 

              <interceptor-ref name="defaultStack" /> 

              <interceptor-ref name="checkLogin" /> 

           </interceptor-stack> 

</interceptors> 

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



参数问题:即<param../>的使用: 

系统为拦截器指定参数有两个时机: 

1.定义拦截器时指定参数值(通过<interceptor .../>元素来定义拦截器,参数就是它下面的<param name="参数">参数值</param>):这种参数值是拦截器这个参数的默认数值。 

2.使用拦截器时指定参数值(通过<interceptor-ref.../>元素来使用拦截器参数就是它下面的<param name="参数">参数值</param>):这种参数值是当在Action中使用该拦截器时动态分配的参数值。 



无论在哪里里面配置,他的值都是传给拦截器类。 



另外,struts2还为我们提供了一个方法过滤的拦截器MethodFilterInterceptor类,该类继承 AbstractInterceptor类,重写了intercept(ActionInvocation invocation)并提供了一个新的方法doInterceptor(ActionInvocation invocation)抽象方法。该类的使用方法很简单,跟上例类似,就不举例了。这个拦截器与以往的拦截器配置有所不同。那就是可以指定哪些方法需要被 拦截,那些不需要。通常在引用该拦截器时指定。 


<interceptor-ref name="  "> 

       <param name="exculdeMethods"></param> 

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

</interceptor-ref> 

exculdeMethods:是不被拦截的方法,如果有多个以逗号分隔。 
includeMethods:需要被拦截的方法,如果有多个以逗号分隔。 



上面两个参数,在MethodFilterInterceptor类中都有对应的方法。 

如果一个方法同时在这两个方法中列出,则该方法会被拦截。 





struts2中提供了这种方法过滤的拦截器有如下几个: 

1.TokenInterceptor 

2.TokenSessionStoreInterceptor 

3.DefaultWorkflowInterceptor 

4.ValudationInterceptor 



三、覆盖特定拦截器的参数 

<拦截器名>.<参数名> 



<interceptor-ref name="my-stack"> 

    <!--second为拦截器名,name为参数名--> 

    <param name="second.name">改名后的拦截器</param> 

</interceptor-ref> 





四、拦截结果的监听器 

  实现拦截结果的监听器首先必须现实com.opensymphony.xwork2.interceptor.PreResultListener类 
并重写里面的方法beforeResult : 



public class MyListener implements PreResultListener {   

  

    public void beforeResult(ActionInvocation invocation, String resultCode) {   



        System.out.println(resultCode);   



    }   



参数介绍: 

1.虽然beforeResult方法也获得ActionInvocation类型的参数,但通过这个参数来控制Action的作用已经不再明显--因为Action的execute方法已经执行结束了。 

2.resultCode,这个参数就是被拦截Action的execute方法的返回值。 





然后再在拦截器里面调用 

invocation.addPreResultListener(new MyListener()); 



拦截器结果监听器是在系统处理Result之前,在execute之后执行的。 



注意:不要在PreResultListener监听器的beforeResult方法中通过ActionInvocation参数调用invoke方法。否则容易造成死循环。

原文地址:https://www.cnblogs.com/zuiyirenjian/p/3980381.html