struts2(五)之struts2拦截器与自定义拦截器 一、struts2拦截器概述 二、自定义拦截器 三、拦截器应用 四、案例中的问题

前言

  前面介绍了struts2的输入验证,如果让我自己选的话,肯定是选择xml配置校验的方法,因为,能使用struts2中的一些校验规则,就无需自己编写了,

  不过到后面应该都有其他更方便的校验方法,而不会使用struts2内置的这些校验。

  参考博文:http://www.cnblogs.com/whgk/p/6593916.html

       http://www.cnblogs.com/cxyzyh2017/p/6622827.html        

  1)什么是拦截器?

  Struts2中的很多功能都是由拦截器完成的。比如:servletConfig,staticParam,params,modelDriven等等。

  现在应该都知道了,前面说表单提交参数自动封装时就提到了好几种拦截器,而上面说校验数据也提到了两种拦截器,基本上我们也知道拦截器的作用是啥了,

  就是在到达action之前做的很多处理,提前帮我们做事情的一种机制,而我们并不需要编写这些拦截器,因为struts2已经帮我们写好了常用的一些拦截器并且

  有个defaultStack的拦截器栈,我们使用的action就经过struts2提供的这个默认拦截器栈。其中有18个,也就是说,如果不修改默认拦截器栈,那么每次我们访

  问action,都会经过这18个拦截器栈,我们来看看哪18个。

  2)struts2的默认拦截器栈(18个拦截器)

    struts2(五)之struts2拦截器与自定义拦截器
一、struts2拦截器概述
二、自定义拦截器
三、拦截器应用
四、案例中的问题

  找到defaultStack

    struts2(五)之struts2拦截器与自定义拦截器
一、struts2拦截器概述
二、自定义拦截器
三、拦截器应用
四、案例中的问题

  其中我们应该了解很多个了,277行,i18n用来做国际化,281行,modeDriven用来数据封装的,282行fileUpload,上传下载的,285行staticParams用来获取

  静态参数的,287行params用做数据封装的,290行conversionError标识数据类型转换异常处理的,291行,validation用来做输入校验的 292行workflow用来

  检测<filederror>是否有值,有值则跳到input结果码对应的页面。

  3)拦截器的执行时机

  struts2(五)之struts2拦截器与自定义拦截器
一、struts2拦截器概述
二、自定义拦截器
三、拦截器应用
四、案例中的问题

二、自定义拦截器

  struts2(五)之struts2拦截器与自定义拦截器
一、struts2拦截器概述
二、自定义拦截器
三、拦截器应用
四、案例中的问题

  大多数功能的拦截器struts2都已经帮我们写好了,但是有一些,我们需要自己在往其中功能,那就必须自定义拦截器了。自定义拦截器很简单,就分两步即可:

    1)编写拦截器类,继承AbstractInterceptor类。(它帮我们实现了Interceptor接口)

    2)注册拦截器 

      在<package>声明拦截器

        在<action>中引用拦截器

  1).编写一个类,继承AbstractInterceptor类或者实现Interceptor接口。重写intercept方法。

    struts2(五)之struts2拦截器与自定义拦截器
一、struts2拦截器概述
二、自定义拦截器
三、拦截器应用
四、案例中的问题

  2)配置拦截器:注意拦截器必须先声明后使用

    struts2(五)之struts2拦截器与自定义拦截器
一、struts2拦截器概述
二、自定义拦截器
三、拦截器应用
四、案例中的问题

  3)测试拦截器的执行顺序

    访问:

      struts2(五)之struts2拦截器与自定义拦截器
一、struts2拦截器概述
二、自定义拦截器
三、拦截器应用
四、案例中的问题

    结果:

      struts2(五)之struts2拦截器与自定义拦截器
一、struts2拦截器概述
二、自定义拦截器
三、拦截器应用
四、案例中的问题

  4)多个拦截器的执行顺序

    struts.xml中的配置

    struts2(五)之struts2拦截器与自定义拦截器
一、struts2拦截器概述
二、自定义拦截器
三、拦截器应用
四、案例中的问题

    编写两个自定义拦截器

    struts2(五)之struts2拦截器与自定义拦截器
一、struts2拦截器概述
二、自定义拦截器
三、拦截器应用
四、案例中的问题

    执行结果:

    struts2(五)之struts2拦截器与自定义拦截器
一、struts2拦截器概述
二、自定义拦截器
三、拦截器应用
四、案例中的问题

  问题:一旦为Action指定了拦截器,那么就不会再为这个Action执行默认拦截器了,这个怎么解决?

    比如:

    struts2(五)之struts2拦截器与自定义拦截器
一、struts2拦截器概述
二、自定义拦截器
三、拦截器应用
四、案例中的问题

    上图所示一般不用这种,因为Struts2有这么一种机制,一旦为Action指定了拦截器,那么就不会再为这个Action执行默认拦截器了,即

    defaultStack这个拦截器栈中的拦截器都不会执行,也就是说,这个Action没有输入校验、没有参数注入、没有国际化、没有…,这是不

    行的,所以我们需要在这个<action>元素中再引用defaultStack拦截器栈

    struts2(五)之struts2拦截器与自定义拦截器
一、struts2拦截器概述
二、自定义拦截器
三、拦截器应用
四、案例中的问题

    这种虽然达到了我们的效果,但是非常麻烦,因为只有一个action,如果有十几个action呢?需要为每个action配置默认拦截器栈和自定义拦

    截器,所以使用最后一种方案。

    终极方案:创建一个拦截器栈,将默认拦截器栈和自定义拦截器加入其中,然后将struts2的默认拦截器栈修改为我们新构建的拦截器栈

    struts2(五)之struts2拦截器与自定义拦截器
一、struts2拦截器概述
二、自定义拦截器
三、拦截器应用
四、案例中的问题

三、拦截器应用

  1)页面

    login.jsp

    struts2(五)之struts2拦截器与自定义拦截器
一、struts2拦截器概述
二、自定义拦截器
三、拦截器应用
四、案例中的问题

    main.jsp

    struts2(五)之struts2拦截器与自定义拦截器
一、struts2拦截器概述
二、自定义拦截器
三、拦截器应用
四、案例中的问题

    otherPage.jsp

    struts2(五)之struts2拦截器与自定义拦截器
一、struts2拦截器概述
二、自定义拦截器
三、拦截器应用
四、案例中的问题

  2)struts.xml

    struts2(五)之struts2拦截器与自定义拦截器
一、struts2拦截器概述
二、自定义拦截器
三、拦截器应用
四、案例中的问题

  3)Demo2Action.java

    struts2(五)之struts2拦截器与自定义拦截器
一、struts2拦截器概述
二、自定义拦截器
三、拦截器应用
四、案例中的问题

  4)checkLoginInterceptor.java拦截器

    struts2(五)之struts2拦截器与自定义拦截器
一、struts2拦截器概述
二、自定义拦截器
三、拦截器应用
四、案例中的问题

  5)测试

    因为我们用来测试的,所以我们在动作类中直接就给user赋值了,相当于就是登录了。

    struts2(五)之struts2拦截器与自定义拦截器
一、struts2拦截器概述
二、自定义拦截器
三、拦截器应用
四、案例中的问题

    然后跳转到主页

    struts2(五)之struts2拦截器与自定义拦截器
一、struts2拦截器概述
二、自定义拦截器
三、拦截器应用
四、案例中的问题

    点击另一个页面

    struts2(五)之struts2拦截器与自定义拦截器
一、struts2拦截器概述
二、自定义拦截器
三、拦截器应用
四、案例中的问题

四、案例中的问题

  1)问题一:由于我们写了自己的拦截器,默认的拦截器就不起作用了。

   解决办法:把默认的拦截器加到配置文件中  

<package name="p2" extends="struts-default">
        <interceptors>声明拦截器
            <interceptor name="checkLoginInterceptor" class="com.jxlg.web.interceptor.CheckLoginInterceptor" />
        </interceptors>
        <global-results>全局结果视图
            <result name="input">/login.jsp</result>数据回显的结果视图
        </global-results>
        用户登录时,不需要检查登录的拦截器工作
        <action name="login" class="com.jxlg.web.action.Demo2Action" method="login">
            <result type="redirectAction">showMain</result>
        </action>
        前往主页的动作名称,需要检查登录的拦截器工作
        <action name="showMain" class="com.jxlg.web.action.Demo2Action" >
            <interceptor-ref name="checkLoginInterceptor"></interceptor-ref>
             <interceptor-ref name="defaultStack"></interceptor-ref>    
            <result>/main.jsp</result>
        </action>
        前往另一个页面的动作名称,需要检查登录的拦截器工作
        <action name="showOther" class="com.jxlg.web.action.Demo2Action" >
            <interceptor-ref name="checkLoginInterceptor"></interceptor-ref>
            <interceptor-ref name="defaultStack"></interceptor-ref>   
            <result>/otherpage.jsp</result>
        </action>
    </package>

  2)问题二:上面1中还是存在问题。当有多个拦截器时,需要改写的内容很多

    解决方法:抽取公共包,把全局配置放入公共包中

<package name="p2" extends="struts-default">
        <interceptors>
            <interceptor name="checkLoginInterceptor" class="com.jxlg.web.interceptor.CheckLoginInterceptor" />
            定义一个拦截器栈,把我们自定义的拦截器和默认的拦截器栈放到一起.
            <interceptor-stack name="myDefaultStack">
                <interceptor-ref name="defaultStack"></interceptor-ref>
                <interceptor-ref name="checkLoginInterceptor"></interceptor-ref>
            </interceptor-stack>
        </interceptors>
        <global-results>
            <result name="input">/login.jsp</result>
        </global-results>
        <action name="login" class="com.jxlg.web.action.Demo2Action" method="login">
            <result type="redirectAction">showMain</result>
        </action>
        <action name="showMain" class="com.jxlg.web.action.Demo2Action" >
            直接引入我们自己定义的拦截器栈,里面已经包含了默认的拦截器栈
            <interceptor-ref name="myDefaultStack"></interceptor-ref>
            <result>/main.jsp</result>
        </action>
        <action name="showOther" class="com.jxlg.web.action.Demo2Action" >
            直接引入我们自己定义的拦截器栈,里面已经包含了默认的拦截器栈
            <interceptor-ref name="myDefaultStack"></interceptor-ref>
            <result>/otherpage.jsp</result>
        </action>
    </package>

struts.xml

  3)问题:还要在每个动作方法中引入自定义的拦截器栈,能不能不用呢?

   解决方法:我们在设置【开发模式】时,覆盖掉了一个default.properties中的常量,能不能把struts-default.xml中的默认拦截器栈的设置给覆盖掉呢?答案是可以的。 

   struts2(五)之struts2拦截器与自定义拦截器
一、struts2拦截器概述
二、自定义拦截器
三、拦截器应用
四、案例中的问题

<package name="p2" extends="struts-default">
        <interceptors>
            <interceptor name="checkLoginInterceptor" class="com.jxlg.web.interceptor.CheckLoginInterceptor" />
            <interceptor-stack name="myDefaultStack">
                <interceptor-ref name="defaultStack"></interceptor-ref>
                <interceptor-ref name="checkLoginInterceptor"></interceptor-ref>
            </interceptor-stack>
        </interceptors>
        覆盖了struts-default.xml中定义的默认拦截器栈。由myDefaultStack把defaultStack给替换了
        <default-interceptor-ref name="myDefaultStack"></default-interceptor-ref>
        <global-results>
            <result name="input">/login.jsp</result>
        </global-results>
        <action name="login" class="com.jxlg.web.action.Demo2Action" method="login">
            <result type="redirectAction">showMain</result>
        </action>
        <action name="showMain" class="com.jxlg.web.action.Demo2Action" >
            <result>/main.jsp</result>
        </action>
        <action name="showOther" class="com.jxlg.web.action.Demo2Action" >
            <result>/otherpage.jsp</result>
        </action>
    </package>

  4)问题:当使用默认的拦截器栈,这时候三个动作都会被检查登录拦截。但是我们第一个动作方法login()不需要拦截器呀?

    解决方法:需要通过AbstractInterceptor类的子类入手,通过查看发现,该类还有一个子类是抽象的。

    struts2(五)之struts2拦截器与自定义拦截器
一、struts2拦截器概述
二、自定义拦截器
三、拦截器应用
四、案例中的问题

    在AbstractInterceptor的子类中,还有一个抽象类MethodFilterInterceptor,它里面提供了两个属性
        excludeMethods:哪些方法不需要拦截
        includeMethods:哪些方法需要拦截

    struts2(五)之struts2拦截器与自定义拦截器
一、struts2拦截器概述
二、自定义拦截器
三、拦截器应用
四、案例中的问题

    struts2(五)之struts2拦截器与自定义拦截器
一、struts2拦截器概述
二、自定义拦截器
三、拦截器应用
四、案例中的问题

    重新写拦截器类,这次我们继承MethodFilterInterceptor

package com.itheima.web.interceptor;

import javax.servlet.http.HttpSession;

import org.apache.struts2.ServletActionContext;

import com.opensymphony.xwork2.ActionInvocation;
import com.opensymphony.xwork2.interceptor.MethodFilterInterceptor;
/**
 * 检查登录的拦截器,最终版本
 * @author zhy
 *
 */
public class CheckLoginInterceptor1 extends MethodFilterInterceptor {

    public String doIntercept(ActionInvocation invocation) throws Exception {
        //1.获取HttpSession
        HttpSession session = ServletActionContext.getRequest().getSession();
        //2.获取session域中的登录标记
        Object obj = session.getAttribute("user");
        //3.判断是否有登录标记
        if(obj == null){
            //用户没有登录
            return "input";
        }
        //4.用户登录了,放行
        String rtValue = invocation.invoke();
        return rtValue;
    }

}

  并且在struts的配置文件中,配置需要拦截哪些方法,和需要放过哪些方法。

<package name="p2" extends="struts-default">
        <interceptors>
            <interceptor name="checkLoginInterceptor1" class="com.jxlg.web.interceptor.CheckLoginInterceptor1" />
            <interceptor-stack name="myDefaultStack">
                <interceptor-ref name="defaultStack"></interceptor-ref>
                <interceptor-ref name="checkLoginInterceptor1">
                    给自定义拦截器注入参数,告知他哪些方法不需要拦截
                    <param name="excludeMethods">login</param>
                </interceptor-ref>
            </interceptor-stack>
        </interceptors>
        <default-interceptor-ref name="myDefaultStack"></default-interceptor-ref>
        <global-results>
            <result name="input">/login.jsp</result>
        </global-results>
        <action name="login" class="com.jxlg.web.action.Demo2Action" method="login">
            <result type="redirectAction">showMain</result>
        </action>
        <action name="showMain" class="com.jxlg.web.action.Demo2Action" >
            <result>/main.jsp</result>
        </action>
        <action name="showOther" class="com.jxlg.web.action.Demo2Action" >
            <result>/otherpage.jsp</result>
        </action>
    </package>

struts.xml

  5)问题:我们在声明时配置了哪些方法需要拦截,哪些方法不需要拦截。但是在没有写动作类和动作方法之前,不确定方法名叫什么。

    解决方法:我们需要在使用拦截器的时候给它注入参数。告诉拦截器哪些需要拦截,哪些不需要

package name="p2" extends="struts-default">
        <interceptors>
            <interceptor name="checkLoginInterceptor1" class="com.jxlg.web.interceptor.CheckLoginInterceptor1" />
            <interceptor-stack name="myDefaultStack">
                <interceptor-ref name="defaultStack"></interceptor-ref>
                <interceptor-ref name="checkLoginInterceptor1"></interceptor-ref>
            </interceptor-stack>
        </interceptors>
        <default-interceptor-ref name="myDefaultStack"></default-interceptor-ref>
        <global-results>
            <result name="input">/login.jsp</result>
        </global-results>
        
        <action name="login" class="com.jxlg.web.action.Demo2Action" method="login">
            <interceptor-ref name="myDefaultStack">
                <!-- 在引用自定义拦截器栈的时候,给指定的拦截器注入参数。方式就是:拦截器名称.属性名称 -->
                <param name="checkLoginInterceptor1.excludeMethods">login</param>
            </interceptor-ref>
            <result type="redirectAction">showMain</result>
        </action>
        <action name="showMain" class="com.jxlg.web.action.Demo2Action" >
            <result>/main.jsp</result>
        </action>        
        <action name="showOther" class="com.jxlg.web.action.Demo2Action" >
            <result>/otherpage.jsp</result>
        </action>
    </package>

struts.xml

  所以在以后的开发中就都是用这种形式

  struts2(五)之struts2拦截器与自定义拦截器
一、struts2拦截器概述
二、自定义拦截器
三、拦截器应用
四、案例中的问题

  

 喜欢就“推荐”哦!