• Struts2 拦截器


    Filter、Interceptor都是AOP思想的体现。

    Filter(过滤器)会拦截所有的请求,对html、jsp、Servlet等资源的请求都会被拦截。

    Interceptor(拦截器)只拦截对Action的请求,且可以实现细粒化拦截,可以只拦截Action中的部分方法。

    拦截器是struts2的灵魂,struts2自带了大量的拦截器,实现了struts2的大部分功能。

    Filter、Interceptor的执行顺序都是:去的时候依次执行1,2,3,回来的时候就依次执行3,2,1。

    因为是在1里面放行,调用2,在2里面放行,调用3,3里面放行调用Action|Servlet|JSP|html,得到响应对象,

    响应对象返还给3,3对响应对象进行处理,返回给2,2对响应对象进行处理,返回给1,1对响应对象进行处理,返回给服务器,服务器返回给浏览器。

    相当于递归调用。

    注意是先调用JSP,由JSP组成响应,再由拦截器对响应进行进一步处理。

    拦截器能拦截请求,也能拦截响应。


    拦截器的配置

    <struts>
        <package name="action" namespace="/action" extends="struts-default">
            <interceptors>
                <interceptor name="" class=""></interceptor>
                
                <interceptor-stack name="">
                    <interceptor-ref name=""></interceptor-ref>
                    <interceptor-ref name=""></interceptor-ref>
                    <interceptor-ref name=""></interceptor-ref>
                </interceptor-stack>
            </interceptors>
            
            <default-interceptor-ref name=""></default-interceptor-ref>
    
            
            <action name="" class="">
                <interceptor-ref name="defaultStack"></interceptor-ref>
                <interceptor-ref name=""></interceptor-ref>
    
                <result name=""></result>
                <result name=""></result>
            </action>
    
        </package>
    
    </struts>

    在<interceptors>中注册拦截器、拦截器栈,注册之后就可以通过name来引用拦截器、拦截器栈。可以用拦截器栈来组合一组拦截器。

    <default-interceptor-ref name=""></default-interceptor-ref>配置默认引用的拦截器、拦截器栈,此配置会覆盖struts-default.xml中的默认拦截器配置。如果我们配置了拦截器、拦截器栈的引用,就不会再自动调用默认的;如果我们没有配置拦截器、拦截器栈的引用,会自动调用默认的。

    <interceptors>、<default-interceptor-ref>均只能作为<package>的子元素来配置。

    在<action>中使用<interceptor-ref>来引用拦截器、拦截器栈,可同时引用多个,默认拦截器栈中有很多通用处理,一般都要引用。

    <interceptor-ref>只能作为<action>的子元素来配置。

    去的时候,按照引用的先后顺序依次调用拦截器,回来的时候,调用顺序相反。

    struts-default.xml中的默认拦截器配置:

    <interceptor-stack name="defaultStack">
                    <interceptor-ref name="exception"/>
                    <interceptor-ref name="alias"/>
                    <interceptor-ref name="servletConfig"/>
                    <interceptor-ref name="i18n"/>
                    <interceptor-ref name="prepare"/>
                    <interceptor-ref name="chain"/>
                    <interceptor-ref name="scopedModelDriven"/>
                    <interceptor-ref name="modelDriven"/>
                    <interceptor-ref name="fileUpload"/>
                    <interceptor-ref name="checkbox"/>
                    <interceptor-ref name="datetime"/>
                    <interceptor-ref name="multiselect"/>
                    <interceptor-ref name="staticParams"/>
                    <interceptor-ref name="actionMappingParams"/>
                    <interceptor-ref name="params"/>
                    <interceptor-ref name="conversionError"/>
                    <interceptor-ref name="validation">
                        <param name="excludeMethods">input,back,cancel,browse</param>
                    </interceptor-ref>
                    <interceptor-ref name="workflow">
                        <param name="excludeMethods">input,back,cancel,browse</param>
                    </interceptor-ref>
                    <interceptor-ref name="debugging"/>
                </interceptor-stack>

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

    servletConfig拦截器用于获取原生的Servlet API。

    modelDriven用于模型驱动获取参数。

    fileUpload用于文件上传。

    params用于封装请求参数。

    .........

    默认的拦截器(栈)有大量的通用操作,一般都要引用。如果不引用默认的拦截器(栈),struts2的很多功能都用不了。

    拦截器是Struts2的核心,完成了Struts2的大部分工作,比如解析请求参数、将请求参数赋给Action的成员变量,数据校验,文件上传等。

    Struts2的拦截器是可插拔式设计,要使用某个拦截器,在配置文件中引入即可,不使用时在配置文件中删除即可。


    自定义拦截器类

    Interceptor本质是一个Java类,新建一个Java类即可。有3种方式:

    • 实现Interceptor接口       需实现里面所有的抽象方法
    • 实现AbstractInterceptor抽象类    这个类是Interceptor的子类,为其它方法提供了空实现,只有核心方法intercept()是抽象的。实现intercept()方法即可。
    • 实现MethodFilterInterceptor抽象类    这个类是AbstractInterceptor的(抽象)子类,可以只拦截Action中的部分方法。需要实现doIntercept()方法。

    Interceptor接口:

    public interface Interceptor extends Serializable {
        void destroy();
    
        void init();
    
        String intercept(ActionInvocation var1) throws Exception;
    }

    在init()中做初始化,在destroy中清理善后,intercept()是核心方法,用于拦截处理。

    使用AbstractInterceptor:

    public class MyInterceptor extends AbstractInterceptor {
        @Override
        public String intercept(ActionInvocation actionInvocation) throws Exception {
            //去的时候做一些处理
            System.out.println("before");
            
            //放行
            String result = actionInvocation.invoke();
            
            //回来的时候做一些处理
            System.out.println("after");
            
            return result;
        }
    }

    需要返回String,如果需要在回来的时候做一些处理,要将return放到最后。

    返回的String就是action返回的那个String,如果不想进行后续处理,不调用 actionInvocation.invoke() ,直接返回一个String(逻辑视图名)即可。

    如果不调用JSP来显示,可以 return null; 。

    使用MethodFilterInterceptor拦截action中的部分方法:

    public class MyInterceptor extends MethodFilterInterceptor {
        @Override
        protected String doIntercept(ActionInvocation actionInvocation) throws Exception {
            //去的时候做一些处理
            System.out.println("before");
            
            //放行
            String result = actionInvocation.invoke();
            
            //回来的时候做一些处理
            System.out.println("after");
            
            return result;
        }
    }

    Action中有多个处理业务的方法:

    public class MyAction{
        public String add(){
            System.out.println("add");
            return "ok";
        }
    
        public String update(){
            System.out.println("update");
            return "ok";
        }
    
        public String delete(){
            System.out.println("delete");
            return "ok";
        }
    }

    拦截器配置:

    <struts>
        <package name="action" namespace="/" extends="struts-default">
            <interceptors>
                <interceptor name="myInterceptor" class="interceptor.MyInterceptor">
                    <param name="includeMethods">add,delete</param>
                </interceptor>
            </interceptors>
    <action name="MyAction_*" class="action.MyAction" method="{1}"> <interceptor-ref name="defaultStack"></interceptor-ref> <interceptor-ref name="myInterceptor"></interceptor-ref> <result name="ok">/index.jsp</result> <allowed-methods>add,update,delete</allowed-methods> </action> </package> </struts>

    MethodFilterInterceptor常与Action动态方法调用搭配使用。

    注册拦截器时,需指定要拦截的方法|不拦截的方法:

    <interceptor name="myInterceptor" class="interceptor.MyInterceptor">
             <param name="includeMethods">add,delete</param>
             <param name="excludeMethods">update</param>
    </interceptor>

    includeMethods指定此拦截器要拦截的方法,excludeMehtods指定不拦截的方法,这2个参数不能一起使用。指定了其中一个,剩下的方法都是另一个的。

    要调用的方法是includeMethods中的方法时,才会使用此拦截器进行拦截,否则不使用此拦截器进行拦截。

    此例中,访问MyAction_add、MyAcion_delete时,均会调用此拦截器;访问MyAction_update时,不会调用此拦截器。

    处理机制:请求传递给此拦截器,此拦截器检查要调用的方法是否是includeMethods中的方法,是就处理,不是就直接放行。


    Interceptor的生命周期

    Interceptor在部署|启动WebApp时就创建实例,调用init()进行初始化。

    从Tomcat中移除当前WebApp时,Interceptor实例随着WebApp的销毁而销毁,会自动调用destroy()。

    Interceptor是单例的,一个Interceptor在Tomcat中只有一个实例。

    在Interceptor的生命周期中,init()、destroy()均只调用1次。每次拦截请求都会调用核心拦截方法。

    Action是多例的,每次处理请求都会创建一个新的Action实例。

    处理完业务,调用JSP之后,此Action的生命周期才结束。

    注意是执行要调用的JSP之后,Action实例才销毁。就是说在执行JSP时,此Action的ValueStack还在,仍可以从中取出数据。


    使用Interceptor实现权限校验

    用户登录,登录成功后可执行相关操作,直接执行用户操作,不再检查用户权限、信息,这是不行的。

    比如用户可以直接在地址栏输入URL,转到操作页面进行操作,跳过用户登录。

    可以使用拦截器拦截用户请求,检查用户权限:

    从session中获取用户信息、权限,如果满足条件,就放行,如果未登录、权限不够,就转发到对应的登录页面、提示页面。

    在用户登录成功时,将用户信息、权限放到session中。

    可使用MethodFilterInterceptor只拦截Action中需要检查权限的某些方法。

  • 相关阅读:
    DateTime 格式化示例
    Linq To XML概述[转]
    .net邮件发送代码
    ASP.NET中c#的URL编码处理
    消息队列(Message Queue)简介及其使用
    C#多线程学习笔记之(abort与join配合使用)
    异常处理的性能损失
    推荐一款DataGridView的打印解决方案
    玩转App.Config
    推荐一个快速反射调用的类
  • 原文地址:https://www.cnblogs.com/chy18883701161/p/11483245.html
Copyright © 2020-2023  润新知