前言

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

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

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

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

一、struts2拦截器概述

  1)什么是拦截器?

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

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

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

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

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

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

    

  找到defaultStack

    

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

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

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

  3)拦截器的执行时机

  

二、自定义拦截器

  

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

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

    2)注册拦截器

      在<package>声明拦截器

        在<action>中引用拦截器

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

    

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

    

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

    访问:

      

    结果:

      

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

    struts.xml中的配置

    

    编写两个自定义拦截器

    

    执行结果:

    

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

    比如:

    

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

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

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

    

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

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

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

    

三、拦截器应用

  1)页面

    login.jsp

    

    main.jsp

    

    otherPage.jsp

    

  2)struts.xml

    

  3)Demo2Action.java

    

  4)checkLoginInterceptor.java拦截器

    

  5)测试

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

    

    然后跳转到主页

    

    点击另一个页面

    

四、案例中的问题

  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中的默认拦截器栈的设置给覆盖掉呢?答案是可以的。 

   

<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类的子类入手,通过查看发现,该类还有一个子类是抽象的。

    

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

    

    

    重新写拦截器类,这次我们继承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拦截器与自定义拦截器的更多相关文章

  1. CXF添加拦截器和自定义拦截器

    前面讲了如何采用CXF开发webservice,现在来讲如何添加拦截器和自定义拦截器. 服务端代码: HelloWorld implementor=new HelloWorldImpl(); Stri ...

  2. flask之web网关、三件套、配置、路由(参数、转化器及自定义转化器)、cbv、模板语言、session

    目录 1.wsgiref.py 2.werzeug.py 3.三件套 4.配置文件 5.路由本质 6.cbv.py 7.路由转化器 8.自定义转化器 9.模板语言 10.session原理 11.te ...

  3. Elasticsearch修改分词器以及自定义分词器

    Elasticsearch修改分词器以及自定义分词器 参考博客:https://blog.csdn.net/shuimofengyang/article/details/88973597

  4. struts2内置拦截器和自定义拦截器详解(附源码)

    一.Struts2内置拦截器 Struts2中内置类许多的拦截器,它们提供了许多Struts2的核心功能和可选的高级特 性.这些内置的拦截器在struts-default.xml中配置.只有配置了拦截 ...

  5. 从struts2拦截器到自定义拦截器

    拦截器可谓struts2的核心了,最基本的bean的注入就是通过默认的拦截器实现的,一般在struts2.xml的配置中,package内直接或间接继承了struts-default.xml,这样st ...

  6. Struts2第七篇【介绍拦截器、自定义拦截器、执行流程、应用】

    什么是拦截器 拦截器Interceptor-..拦截器是Struts的概念,它与过滤器是类似的-可以近似于看作是过滤器 为什么我们要使用拦截器 前面在介绍Struts的时候已经讲解过了,Struts为 ...

  7. 使用struts2中默认的拦截器以及自定义拦截器

    转自:http://blog.sina.com.cn/s/blog_82f01d350101echs.html 如何使用struts2拦截器,或者自定义拦截器.特别注意,在使用拦截器的时候,在Acti ...

  8. 初学者易上手的SSH-struts2 05拦截器与自定义拦截器

    因为自己对于struts2也不是很了解,这章将是struts2的最后一章了.那么这一章主要介绍的是拦截器以及怎么样来自定义一个拦截器. struts2的拦截器位于struts2-core(核心包)-& ...

  9. Elasticsearch笔记六之中文分词器及自定义分词器

    中文分词器 在lunix下执行下列命令,可以看到本来应该按照中文"北京大学"来查询结果es将其分拆为"北","京","大" ...

随机推荐

  1. 使用VUE模仿BOSS直聘APP

    一.碎碎念: 偶尔在群里看到一个小伙伴说:最近面试的人好多都说用vue做过一个饿了么.当时有种莫名想笑. 为何不知道创新一下?于是想写个DEMO演练一下.那去模仿谁呢?还是BOSS直聘(跟我没关系,不 ...

  2. XML的序列化(Serializer)

    步骤: //1获取XmlSerializer 类的实例 通过Xml这个工具类去获取 XmlSerializer xmlSerializer = Xml.newSerializer(); try { / ...

  3. 翻译 | 使用A-Frame打造WebVR版《我的世界》

    原文地址:Minecraft in WebVR with HTML Using A-Frame 原文作者:Kevin Ngo 译者:Felix 校对:阿希 我是 Kevin Ngo,一名就职于 Moz ...

  4. Java代理和动态代理

    code from <Thinking in java> 代理模式 interface Interface { void doSomething(); void somethingElse ...

  5. Ubuntu16.04.1安装JDK1.8.0

    今天在安装Zookeeper的时候需要安装JDK,对于.Neter来说还是有点陌生,下面我就把安装JDK的步骤记录一下,分享给大家. 一.下载JDK安装包:http://www.oracle.com/ ...

  6. MySQL优化原理

    前言 说起MySQL的查询优化,相信大家收藏了一堆:不能使用SELECT *.不使用NULL字段.合理创建索引.为字段选择合适的数据类型..... 你是否真的理解这些优化技巧?是否理解其背后的工作原理 ...

  7. Nim or not Nim? hdu3032 SG值打表找规律

    Nim or not Nim? Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)T ...

  8. 初入APP(结合mui框架进行页面搭建)

      前  言 博主最近在接触移动APP,学习了几个小技巧,和大家分享一下. 1. 状态栏设置 现在打开绝大多数APP,状态栏都是与APP一体,不仅美观,而且与整体协调.博主是个中度强迫症患者,顶部那个 ...

  9. swoole 入门

    1. 概述 Swoole是PHP的一个扩展,但是它与普通的扩展不同,普通的扩展知识提供一个库函数,而Swoole扩展在运行后会接管PHP的控制器,进入时间循环.当IO时间发生后,Swoole会自动回调 ...

  10. javascript数组的常用方法总结

    http://jingyan.baidu.com/album/86fae346bce16d3c49121af9.html?picindex=1 1. concat()方法 数组和数组的 粘结: var ...