• struts2-第二章-拦截器


    一,回顾

    (1)默认action,404问题;<default-action-ref name="action 名称"/>

    (2)模块化,package,struts.xml

    (3)异常配置,全局异常的作用返回,用一个package,global-result,global-exceptioni-mappings

    (4)结果类型,dispatcher,redirect,chain,redirectAction;action节点的result节点的type属性

    (5)访问servlet容器对象;ActionContext,ServletActionContext,ServletRequestAware,ServletContextAware

    二,DRY原则

    Don't Repeat Yourself      不要写重复的代码

    应该将功能相似的代码封装为方法,在需要的地方直接调用方法即可,若需要修改逻辑代码,我们也只需要修改方法内部的实现就可以,大大减少了维护量,提供工作效率

    三,表单重复提交 

    (1)Demo1Action

    @Getter
    @Setter
    public class Demo1Action extends ActionSupport {
        private String uname;
        private String pname;
        
        
        public String login(){
            System.out.println("姓名:"+uname+",密码:"+pname);
            //传到数据库中,进行匹配
            return SUCCESS;
        }
    }

    (2)struts.xml

    <action name="demo1Action" class="com.yujun.maven.action.Demo1Action">
                <result>/demo1.jsp</result>
    </action>

    (3)demo1.jsp

    (4)运行

    当表单提交后,使用内部方式调用到页面,再次手动刷新页面时就会出现上图所示的重复提交问题;此时点击继续按钮,会发现我们后台的方法代码被重复执行一次;

    解决方案:

      (1)使用重定向来跳转页面

      (2)使用token拦截器

    四,拦截器

    拦截器是动态拦截action调用的对象

    提供一种机制,可以使开发者定义在一个action执行的前后执行的代码,也可以在一个action执行前阻止其执行;通过此机制可以将多个action中重复代码提取到拦截器中定义

    提高代码重用性

      大部分时候,拦截器底层实现都是通过"代理"方式

    struts2拦截器实现相对简单,当请求达到struts2的核心过滤器,struts2查找配置,并根据配置实例化相应的拦截器,然后串成一个列表(list),最后一个一个的调用列表中的拦截器;

    struts2中拦截器是可插拔的(通过配置让其可有可无),拦截器是AOP编程(面向切面)一种实现方式

    struts2连接器栈,就是将拦截器按一定的顺序链接成一条链,在访问被拦截的方法或字段时,struts2拦截器链中的拦截器就会按照自己的顺序依次被调用

     

    注意的是,拦截器执行顺序,来的是和去的时候正好相反

    五,表单重复提交解决

    使用token拦截器的解决方式

    (1)表单页面

    <!-- 防止表单重复提交 -->

    <s:token></s:token>

    (2)struts.xml

    <action name="demo1Action" class="com.yujun.maven.action.Demo1Action">
                <result>/demo1.jsp</result>
                <!-- 当表单重提交时的返回值 -->
                <result name="invalid.token">/demo1_fail.jsp</result>
                <!-- 默认拦截器栈 -->
                <interceptor-ref name="defaultStack"></interceptor-ref>
                <!-- 拦截器引用,token是struts2提供的,防止表单的重复提交 -->
                <interceptor-ref name="token"></interceptor-ref>
            </action>

    (3)demo1_fail.jsp

    <h3>
            你已经提交过一次表单,请勿重复提交!!!
    </h3>

    六,自定义拦截器(重点)

    通常有三种实现方式

    (1) 实现Interceptor接口

    (2)继承Abstractinterceptor类

    (3)继承MethodFilterInterceptor

    1、Interceptor接口

    (1)MyInterceptor1类

    public class MyInterceptor1 implements Interceptor {
        //销毁
        @Override
        public void destroy() {
            System.out.println("MyInterceptor1.destroy...");
        }
        //初始化
        @Override
        public void init() {
            System.out.println("MyInterceptor1.init...");
        }
        //核心
        @Override
        public String intercept(ActionInvocation invocation) throws Exception {
            System.out.println("MyInterceptor1.intercept...start");
            //把请求往下传递
            String result = invocation.invoke();
            System.out.println("MyInterceptor1.intercept...end");
            return result;
        }
    
    }

    (2)struts.xml

    在package节点中声名

    <!-- 声明拦截器 -->
            <interceptors>
                <!-- name:拦截器名称,唯一,class:类全名 -->
                <interceptor name="my1" class="com.yujun.maven.interceptor.MyInterceptor1"></interceptor>
            </interceptors>

    在action节点中使用

    <action name="demo2Action" class="com.yujun.maven.action.Demo2Action">
                <result>/demo2.jsp</result>
                <interceptor-ref name="defaultStack"></interceptor-ref>
                <interceptor-ref name="my1"></interceptor-ref>
     </action>

    注意,这里action中也是需要引用“defaultStack”默认拦截器栈的,因为action一旦配置拦截器,默认的拦截器栈就不会生效,这里需要我们手动配置上去

    (3)demo2.jsp

    <h3>
            this is demo2.jsp
    </h3>

    (4)运行

    http://127.0.0.1:8080/struts2-chapter2/demo2Action!m1.action

    2、继承AbstractInterceptor类

    (1)MyInterceptor2类

    public class MyInterceptor2 extends AbstractInterceptor {
    
        @Override
        public String intercept(ActionInvocation invocation) throws Exception {
            System.out.println("MyInterceptor2.intercept...start");
            String result = invocation.invoke(); //把请求往下传递
            System.out.println("MyInterceptor2.intercept...end-"+result);
            return result;
        }
    
    }

    (2)struts.xml

    <!-- 声明拦截器 -->
            <interceptors>
                <!-- name:拦截器名称,唯一,class:类全名 -->
                <interceptor name="my1" class="com.yujun.maven.interceptor.MyInterceptor1"></interceptor>
                <interceptor name="my2" class="com.yujun.maven.interceptor.MyInterceptor2"></interceptor>
            </interceptors>

    使用

    <action name="demo2Action" class="com.yujun.maven.action.Demo2Action">
                <result>/demo2.jsp</result>
                <interceptor-ref name="defaultStack"></interceptor-ref>
                <interceptor-ref name="my1"></interceptor-ref>
                <interceptor-ref name="my2"></interceptor-ref>
            </action>

    (3)运行

    http://127.0.0.1:8080/struts2-chapter2/demo2Action!m1.action

    3、继承MethodFilterInterceptor类

    (1)MyInterceptor3

    public class MyInterceptor3 extends MethodFilterInterceptor {
    
        @Override
        protected String doIntercept(ActionInvocation invocation) throws Exception {
            System.out.println("MyInterceptor3.doIntercept...start");
            String result = invocation.invoke(); //把请求往下传递
            System.out.println("MyInterceptor3.doIntercept...end-"+result);
            return result;
        }
    
    }

    (2)struts.xml

    <!-- 声明拦截器 -->
            <interceptors>
                <!-- name:拦截器名称,唯一,class:类全名 -->
                <interceptor name="my1" class="com.yujun.maven.interceptor.MyInterceptor1"></interceptor>
                <interceptor name="my2" class="com.yujun.maven.interceptor.MyInterceptor2"></interceptor>
                <interceptor name="my3" class="com.yujun.maven.interceptor.MyInterceptor3"></interceptor>
            </interceptors>

    使用

    <action name="demo2Action" class="com.yujun.maven.action.Demo2Action">
                <result>/demo2.jsp</result>
                <interceptor-ref name="defaultStack"></interceptor-ref>
                <interceptor-ref name="my1"></interceptor-ref>
                <interceptor-ref name="my2"></interceptor-ref>
                <interceptor-ref name="my3">
                    <!-- 排除方法(不拦截) -->
                    <param name="excludeMethods">m2,m3</param>
                    <!-- 包含方法(拦截) -->
                    <param name="includeMethods">m1</param>
                </interceptor-ref>
                
            </action>

    4、注意

    前两种方式,会拦截action中所有方法,最后一种方式,如果不配置属性,默认也是拦截所有action中方法

    七、拦截器栈(链)

    将一个个单独的拦截器放入列表中组成一个链

    <!-- 声明拦截器 -->
            <interceptors>
                <!-- name:拦截器名称,唯一,class:类全名 -->
                <interceptor name="my1" class="com.yujun.maven.interceptor.MyInterceptor1"></interceptor>
                <interceptor name="my2" class="com.yujun.maven.interceptor.MyInterceptor2"></interceptor>
                <interceptor name="my3" class="com.yujun.maven.interceptor.MyInterceptor3"></interceptor>
                
                <!-- 把拦截器封装为拦截器栈 -->
                <interceptor-stack name="myStack">
                    <!-- 拦截器引用 -->
                    <interceptor-ref name="my1"></interceptor-ref>
                    <interceptor-ref name="my2"></interceptor-ref>
                    <interceptor-ref name="my3"></interceptor-ref>
                </interceptor-stack>
            </interceptors>

    使用

    <action name="demo2Action" class="com.yujun.maven.action.Demo2Action">
                <result>/demo2.jsp</result>
                <interceptor-ref name="defaultStack"></interceptor-ref>
                <interceptor-ref name="myStack"></interceptor-ref>

    作业:通过struts2拦截器,拦截器未登录

    八、拦截器和过滤器的区别

    (1)拦截器是基于java反射机制,而过滤器是基于函数回调

    (2)过滤器依赖于servlet容器,而拦截器不依赖于servlet容器

    (3)拦截器只会action起作用,而过滤器对所有请求生效(静态资源、action)

    (4)拦截器可以访问action上下文、值栈的对象,而过滤器不行

    (5)在action的声明周期中,拦截器可以多次调用,而过滤器只会在容器初始化时只需一次

    探索:

             请自行新建一个过滤器(filter),在web.xml中进行过滤器注册,在过滤器的核心方法中打印输出语句,最后请求action的目标方法(m1/m2/m3....),到底是过滤器先执行还是拦截器先执行,然后重复访问action中目标方法,再看看控制台输出情况是怎么样的?

  • 相关阅读:
    UOJ #276. 【清华集训2016】汽水
    Luogu P4585 [FJOI2015]火星商店问题
    Luogu P5416 [CTSC2016]时空旅行
    NOIP 2011 提高组初赛错题简析
    Luogu P4068 [SDOI2016]数字配对
    UOJ Easy Round #5
    Codechef September Challenge 2019 Division 2
    Project Euler Problem 675
    AtCoder Grand Contest 037
    拿2k的前端开发都会做些什么?
  • 原文地址:https://www.cnblogs.com/faded8679/p/10756286.html
Copyright © 2020-2023  润新知