zoukankan      html  css  js  c++  java
  • Struts2入门(二)——配置拦截器

    一、前言

    之前便了解过,Struts 2的核心控制器是一个Filter过滤器,负责拦截所有的用户请求,当用户请求发送过来时,会去检测struts.xml是否存在这个action,如果存在,服务器便会自动帮我们跳转到指定的处理类中去处理用户的请求,基本流程如下:

    该流程笔者理解是基本流程,。如果有不对的地方,请下方留言。我会改正。谢谢;

    好,接着往下讲:

    注意:在struts.xml中,配置文件必须有该请求的处理类才能正常跳转,同时,返回SUCCESS字符串的类,必须继承ActionSupport,如果你没有继承,那么就返回"success",同样能够跳转到jsp逻辑视图,但是必须确保你struts.xml有<result name="success">xx.jsp</result>,该标签,具体操作在上一篇文章有介绍过简单例子。

    1.1、了解拦截器

    什么是拦截器,它的作用是什么?

    拦截器,实际上就是对调用方法的改进。

    作用:动态拦截对Action对象的调用,它提供了一种机制可以使开发者可以定义在一个action执行的前后执行的代码,也可以在一个action执行前阻止其执行。同时也是提供了一种可以提取action中可重用的部分的方式。

    拦截器的执行顺序:

    在执行Action的execute方法之前,Struts2会首先执行在struts.xml中引用的拦截器,在执行完所有引用的拦截器的intercept方法后,会执行Action的execute方法。 

    二、实际操作

    2.1、自定义拦截器

    新建一个类继承AbstractInterceptor。

    package com.Interceptor;
    
    import java.util.Date;
    import com.opensymphony.xwork2.ActionInvocation;
    import com.opensymphony.xwork2.interceptor.AbstractInterceptor;
    
    public class MyInterceptor extends AbstractInterceptor {
        private String name;//该属性与struts.xml中的<param name="name">简单拦截器</param>一致,也就是说该name的值是简单拦截器
        public void setName(String name) {
            this.name = name;
        }
    
        //拦截action请求
        @Override
        public String intercept(ActionInvocation arg0) throws Exception {
            //取得被拦截的action
            LoginAction action = (LoginAction)arg0.getAction();
            System.out.println(name+":拦截器的动作------"+"开始执行登录action的时间为:"+new Date());
            long start = System.currentTimeMillis();
            /*
             * ActionInvocation.invoke()就是通知struts2接着干下面的事情
             * 比如 调用下一个拦截器 或 执行下一个Action
             * 就等于退出了你自己编写的这个interceptor了
             * 在这里是去调用action的execute方法,也就是继续执行Struts2 接下来的方法*/
            String result = arg0.invoke(); 
            System.out.println(name+":拦截器的动作------"+"执行完登录action的时间为:"+new Date());
            long end = System.currentTimeMillis();
            System.out.println(name+":拦截器的动作------"+"执行完该action的时间为:"+(end-start)+"毫秒");
            
            System.out.println(result);    //输出的值是:success
            return result;
        }
    }
    /**
     * 该页面的效果如下:
     * 简单拦截器:拦截器的动作------开始执行登录action的时间为:Mon Oct 24 19:06:17 CST 2016
             用户名:admin,密码:123
             简单拦截器:拦截器的动作------执行完登录action的时间为:Mon Oct 24 19:06:18 CST 2016
             简单拦截器:拦截器的动作------执行完该action的时间为:1130毫秒
       success
    
     * */

    在struts.xml中配置

    <?xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE struts PUBLIC
        "-//Apache Software Foundation//DTD Struts Configuration 2.5//EN"
        "http://struts.apache.org/dtds/struts-2.5.dtd">
    <struts>
        
        <!--简单的拦截器  -->
        <package name="Interceptor" extends="struts-default" namespace="/ac">
            <!-- 跳转前拦截 -->
            <interceptors>
                <!-- 声明简单的过滤器 -->
                <interceptor name="Inter" class="com.Interceptor.MyInterceptor">
                    <!--传递name的参数  -->
                    <param name="name">简单拦截器</param>
                </interceptor>
            </interceptors>
            <action name="loginaction" class="com.Interceptor.LoginAction">
                <result name="success">/Interceptor/welcome.jsp</result>
                <result name="input">/Interceptor/error.jsp</result>
                <!--注意:如果不加默认的拦截器的话,那么类型转换不会执行,也就是说不会把文本上的值赋值给实体类  -->
                <interceptor-ref name="defaultStack"/>
                
                <!-- 简单的过滤器,定义在这里告诉拦截器在此处action执行 -->
                <interceptor-ref name="Inter">
                </interceptor-ref>
            </action>
        </package>
    </struts>    

    struts.xml解析:

    <interceptors>:表示声明拦截器

    <interceptor>: 表示定义一个拦截器

    <param>:给该拦截器一个参数,属性为name

    <interceptor-ref name="">:表示该拦截器在这个action中使用。

    新建LoginAction类,继承ActionSupport

    package com.Interceptor;
    
    import com.opensymphony.xwork2.ActionSupport;
    
    //action类处理
    public class LoginAction extends ActionSupport {
        private String username;
        private String pwd;
        public String getUsername() {
            return username;
        }
        public void setUsername(String username) {
            this.username = username;
        }
        public String getPwd() {
            return pwd;
        }
        public void setPwd(String pwd) {
            this.pwd = pwd;
        }
        //默认执行execute方法
        public String execute(){
            System.out.println("用户名:"+username+",密码:"+pwd);
            return SUCCESS;
        }

    新建jsp视图界面

    <%@ page language="java" contentType="text/html; charset=UTF-8"
        pageEncoding="UTF-8"%>
    <%@ taglib uri="/struts-tags" prefix="s"%>    
    <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
    <html>
    <head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    <title>简单的登录拦截</title>
    </head>
    <body>
        <!--如果在struts.xml中,package包中有配置namespace的话,那么在此处就应该配置。不然会报404错误  -->
        <s:form action="loginaction" namespace="/ac"> 
              <s:textfield label="User Name" name="username"/>
              <s:password label="Password" name="pwd" />
               <s:submit/>
          </s:form>  
    </body>
    </html>

    (代码笔者测试没问题)

    2.2、过滤方法:

    拦截器不仅可以定义多个拦截,还可以指定拦截特定的方法。

    struts.xml的配置

    <?xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE struts PUBLIC
        "-//Apache Software Foundation//DTD Struts Configuration 2.5//EN"
        "http://struts.apache.org/dtds/struts-2.5.dtd">
    <struts>
        
        <!--简单的拦截器  -->
        <package name="Interceptor" extends="struts-default" namespace="/ac">
            <!-- 跳转前拦截 -->
            <interceptors>
                <!-- 声明方法过滤器 -->    
                <interceptor name="myMethod" class="com.Interceptor.MyMethodInterceptor">
                    <param name="name">方法过滤拦截器</param>
                </interceptor>
            </interceptors>
            <action name="loginaction" class="com.Interceptor.LoginAction" method="method1"> <!-- 如果是拦截方法的话,改为method="method2" -->
                <result name="success">/Interceptor/welcome.jsp</result>   <!-- /Interceptor是笔者文件夹。别弄错了-->
                <result name="input">/Interceptor/error.jsp</result>
                <!--注意:如果不加默认的拦截器的话,那么类型转换不会执行,也就是说不会把文本上的值赋值给实体类  -->
                <interceptor-ref name="defaultStack"/>
                
                
                <!-- 方法过滤器 -->
                <interceptor-ref name="myMethod">
                    <param name="name">改名后的方法过滤器</param>
                     <param name="includeMethods">method1,method3</param>  <!--表示该方法不被拦截-->
                    <param name="excludeMethods">method2</param>           <!--表示该方法被拦截  -->
                </interceptor-ref>
            </action>
        </package>
    </struts>    

    修改LoginAction类

    package com.Interceptor;
    
    import com.opensymphony.xwork2.ActionSupport;
    
    //action类处理
    public class LoginAction extends ActionSupport {
        private String username;
        private String pwd;
        public String getUsername() {
            return username;
        }
        public void setUsername(String username) {
            this.username = username;
        }
        public String getPwd() {
            return pwd;
        }
        public void setPwd(String pwd) {
            this.pwd = pwd;
        }
    //    过滤的方法
      public String method1() throws Exception {  
            System.out.println("Action执行方法:method1()");  
            return SUCCESS;  
        }  
        public String method2() throws Exception {  
            System.out.println("Action执行方法:method2()");  
            return SUCCESS;  
        }  
     
        public String method3() throws Exception {  
            System.out.println("Action执行方法:method3()");  
            return SUCCESS;  
        }  
        
    }

    新建MyMethodInterceptor类继承MethodFilterInterceptor

    MethodFilterInterceptor类表示你定义的拦截器支持方法过滤。

    package com.Interceptor;
    
    import java.util.Date;
    
    import com.opensymphony.xwork2.ActionInvocation;
    import com.opensymphony.xwork2.interceptor.MethodFilterInterceptor;
    
    //过滤方法
    public class MyMethodInterceptor extends MethodFilterInterceptor {
        private String name;
        public void setName(String name) {
            this.name = name;
        }
        @Override
        protected String doIntercept(ActionInvocation arg0) throws Exception {
            //取得被拦截的action
            LoginAction action = (LoginAction)arg0.getAction();
            System.out.println(name+":拦截器的动作------"+"开始执行登录action的时间为:"+new Date());
            long start = System.currentTimeMillis();
            String result = arg0.invoke(); 
            System.out.println(name+":拦截器的动作------"+"执行完登录action的时间为:"+new Date());
            long end = System.currentTimeMillis();
            System.out.println(name+":拦截器的动作------"+"执行完该action的时间为:"+(end-start)+"毫秒");
            
            System.out.println(result);    //输出的值是:success
            return result;
        }
    
    }

    至于jsp视图,一样,不需要改变。

    得到的结果可以看出来:

    当method="method1"或者是method="method3"的时候,会自动去执行MyMethodInterceptor 的方法doIntercept,然后跳转到welcome.jsp界面。

    当method="method2"的时候,控制台会出现 Action执行方法:method2(),之后便被拦截了。

    以上就是拦截方法的基本代码,例子很简单,但是重在理解。

    可能笔者疑惑,为什么需要过滤方法呢?因为拦截器它会自动拦截所有的方法,回造成资源的损耗,所以有些方法我们可以指定不被拦截。

    2.3、监听过滤器:

    在拦截器中,execute方法执行之前或者之后的方法都被拦截在intercept方法中,这些的结构不够明白,我们可以定义监听,虽然好像没什么用,但是了解一下也挺不错的。

    实现拦截器的监听结果必须实现PreResultListener接口。

    package com.Interceptor;
    
    import com.opensymphony.xwork2.ActionInvocation;
    import com.opensymphony.xwork2.interceptor.PreResultListener;
    
    //过拦截器配置一个监听器
    public class MyPreResultListener implements PreResultListener {
        //定义处理Result之前的行为
        @Override
        public void beforeResult(ActionInvocation arg0, String arg1) {
            System.out.println("返回的逻辑视图为:"+arg1);
        }
    }

    然后MyMethodInterceptor类修改为:

    package com.Interceptor;
    
    import java.util.Date;
    
    import com.opensymphony.xwork2.ActionInvocation;
    import com.opensymphony.xwork2.interceptor.MethodFilterInterceptor;
    
    //过滤方法
    public class MyMethodInterceptor extends MethodFilterInterceptor {
        private String name;
        public void setName(String name) {
            this.name = name;
        }
        @Override
        protected String doIntercept(ActionInvocation arg0) throws Exception {
    
            //将一个拦截结果的监听器注册给拦截器
            arg0.addPreResultListener(new MyPreResultListener());
            System.out.println("execute方法被调用之前的拦截");
            //调用下一个拦截器或者action的执行方法
            String result = arg0.invoke();
            System.out.println("execute方法被调用之后的拦截");
            return result;
        }
    
    }

    以上就是拦截器基本知识,如果有错误的地方,请指正。谢谢。

  • 相关阅读:
    mysql零碎问题合集
    mysql 纵表转横表 需要用join不能直接where连接
    eclipse导出可执行jar包 报main function not found错误
    shell脚本将mysql查询结果制作成csv格式
    linux shell中把句子中的单词提取作为变量值 主要是使用了数组
    linux下文件字符编码转换
    Banner使用
    recyclerview的博客网址需要的权限
    okhttp权限
    Okhttp代码
  • 原文地址:https://www.cnblogs.com/IT-1994/p/5997079.html
Copyright © 2011-2022 走看看