JavaWeb学习:Struts2的拦截器

一、概述

  Interceptor:拦截器,拦截Action的作用(Struts2框架核心功能都是依赖拦截器实现的)

    Filter:过滤器,过滤客户端向服务器发送的请求

    Interceptor:拦截器,拦截客户端对Action的访问,可以拦截Action中具体的方法

二、Struts2的执行流程

  客户端向服务器发送一个Action的请求,执行核心过滤器(StrutsPrepareAndersonExecuteFilter)的doFilter()方法,执行executeAction()方法,执行dispatcher.serviceAction()创建一个Action代理,最终执行的是Action代理中的execute(),execute方法中调用ActionInvocation的invoke方法。在这个方法内部递归执行一组拦截器(完成部分功能),执行完所有拦截器,就会执行目标Action,根据Action的返回的结果进行页面跳转。

  

 三、自定义拦截器

  ①、搭建Struts2的环境(引入jar包、配置web.xml、编写Action、配置struts.xml)

  ②、编写拦截器类(类需要实现Interceptor接口或者继承AbstractInterceptor类)

public class InterceptorDemo1 extends AbstractInterceptor {

    @Override
    public String intercept(ActionInvocation invocation) throws Exception {
    System.out.println("InterceptorDemo1执行");
    
    String result=invocation.invoke();
    
    System.out.println("InterceptorDemo1执行结束");
    return result;//invocation.invoke();
    }
}

    继承AbstractInterceptor类只需要重写intercept()方法,而要实现Interceptor接口的,就需要多写一些方法

  ③、配置拦截器

    Ⅰ、直接引入自定义拦截器

    <package name="interceptorDemo" extends="struts-default" namespace="/">
        <!-- Ⅰ、定义拦截器 -->
        <interceptors>
            <interceptor name="interceptorDemo1" class="com.xxx.interceptor.InterceptorDemo1"/>
            <interceptor name="interceptorDemo2" class="com.xxx.interceptor.InterceptorDemo2"/>
        </interceptors>
        
        <action name="demo1" class="com.xxx.web.action.Demo1Action">
            <result>/demo1/index.jsp</result>
            <!-- Ⅱ、引入拦截器(一旦引入自定义拦截器,默认拦截栈中的拦截器就不会执行了,需要手动引入默认拦截器栈) -->
            <interceptor-ref name="defaultStack"></interceptor-ref>
            <interceptor-ref name="interceptorDemo1"></interceptor-ref>
            <interceptor-ref name="interceptorDemo2"></interceptor-ref>
        </action>
    </package>

    Ⅱ、通过拦截器栈的方式

    <package name="interceptorDemo" extends="struts-default" namespace="/">
        <!-- Ⅰ、定义拦截器 并定义拦截器栈-->
        <interceptors>
            <interceptor name="interceptorDemo1" class="com.xxx.interceptor.InterceptorDemo1"/>
            <interceptor name="interceptorDemo2" class="com.xxx.interceptor.InterceptorDemo2"/>
            
            <!-- Ⅱ、定义拦截器栈 (一旦引入自定义拦截器,默认拦截栈中的拦截器就不会执行了,需要手动引入默认拦截器栈) -->
            <interceptor-stack name="custStack">
                <interceptor-ref name="defaultStack"></interceptor-ref>
                <interceptor-ref name="interceptorDemo1"></interceptor-ref>
                <interceptor-ref name="interceptorDemo2"></interceptor-ref>
            </interceptor-stack>
        </interceptors>
        
        <action name="demo1" class="com.xxx.web.action.Demo1Action">
            <result>/demo1/index.jsp</result>
            <!-- Ⅲ、引入自定义拦截器栈-->
            <interceptor-ref name="custStack"></interceptor-ref>
        </action>
    </package>

    注意:定义拦截器和拦截器栈都是在<package>节点下,而真正使用的拦截器的Action需要在对应的<action>节点中引入的拦截器

四、拦截器中心思想

  就是AOP思想,在不修改程序代码的情况下,对程序进行扩展

  实例:权限拦截器

    ①、创建一个类型继承MethodFilterInterceptor类

public class PrivilegeInterceptor extends MethodFilterInterceptor{

    @Override
    protected String doIntercept(ActionInvocation invocation) throws Exception {
    //判断session是否有用户数据
    User existUser=(User) ServletActionContext.getRequest().getSession().getAttribute("existUser");
    
    if(existUser==null) {
        //输出提示信息
        ActionSupport actionSupport= (ActionSupport) invocation.getAction();
        actionSupport.addActionError("没有登录,无法访问!");
        
        //回到登录页面
        return actionSupport.LOGIN;
    }
    //已经登录,继续执行
    return invocation.invoke();
    }
}

  为什么要继承MethodFilterInterceptor?

    MethodFilterInterceptor中有两个属性:

      excludeMethods(拦截器不会拦截器的方法集合)

      includeMethods(拦截器需要拦截器的方法集合)

    protected Set<String> excludeMethods = Collections.emptySet();
    protected Set<String> includeMethods = Collections.emptySet();

  actionSupport.addActionError()方法,设置输出信息,jsp页面代码如下:

    <s:actionerror/>

    ②、配置拦截器

<package name="crm" extends="struts-default" namespace="/">
        <!-- Ⅰ、定义拦截器 并定义拦截器栈-->
        <interceptors>
            <interceptor name="privilegeInterceptor" class="com.xxx.interceptor.PrivilegeInterceptor"/>
        </interceptors>
        
        <global-allowed-methods>regex:.*</global-allowed-methods>
        
        <!-- 每个action都需要login视图 -->
        <global-results>
            <result name="login">/login.jsp</result>
        </global-results>
        
        <action name="customer_*" class="com.xxx.web.action.CustomerAction" method="{1}">
            <result name="findSuccess">/jsp/customer/list.jsp</result>
            <result name="savaUI">/jsp/customer/add.jsp</result>
            <result name="saveSuccess" type="redirectAction">
                <param name="namespace">/xxxx</param>
                <param name="actionName">xxx_xxx</param>
            </result>
            
            <!-- 引入自定义拦截器,拦截此action中所有方法-->
            <interceptor-ref name="privilegeInterceptor"/>
            <interceptor-ref name="defaultStack"/>
        </action>
        
        <action name="user_*" class="com.xxx.web.action.UserAction" method="{1}">
            <result type="redirect">/index.jsp</result>
            <!-- 引入自定义拦截器-->
            <interceptor-ref name="privilegeInterceptor">
                <!-- 配置excludeMethods节点中的方法不拦截,配置多个方法时以逗号(,)隔开 -->
                <param name="excludeMethods">login,regist</param>
            </interceptor-ref>
            <interceptor-ref name="defaultStack"/>
        </action>
    </package
原文地址:https://www.cnblogs.com/WarBlog/p/14072254.html