拦截器初探

昨天临睡觉之前看了看拦截器,也在昨天的学习笔记里面胡诌诌了几句,今天就来好好的会会拦截器这个东西。实际上拦截器是一种模块实现的机制<起码我是这么体会的>(至于说书里面说体现了AOP的设计思想…我连AOP是啥还没搞清楚好伐…),在struts1的版本里面,struts将所有的功能围绕着核心控制器来实现的,而到了Struts2,控制器不在承担过多的功能支持,将这些功能拓展交给拦截器来完成。

拦截器设计为在action之前或action之后执行,从系统的架构图也能看出来,除了系统核心的拦截器外,你还可以插入其他的拦截器。

拦截器还有一个好处,就是解耦合。比如说A方法中需要验证username长度不能超过25位,B方法也需要,C方法也需要,那么我们就可以考虑将这个验证放在一个拦截器中实现,在执行Action之前执行,如果错误就返回,如果正确继续执行Action。

那么到底拦截器的原理是什么呢?我觉得从struts的书上是找不到答案了,度娘帮一下,下面是度娘给的定义…

java里的拦截器是动态拦截Action调用的对象。它提供了一种机制可以使开发者可以定义在一个action执行的前后执行的代码,也可以在一个action执行前阻止其执行,同时也提供了一种可以提取action中可重用部分的方式。在AOP(Aspect-Oriented Programming)中拦截器用于在某个方法或字段被访问之前,进行拦截然后在之前或之后加入某些操作。

这么一查的倒是提醒我了,有一点很重要,拦截器并非什么特殊的代码,他只是一个Java类,实现起来很简单。还有就是拦截器与过滤器的区别:

过滤器可以简单理解为

取你所想取

忽视掉那些你不想要的东西;拦截器可以简单理解为

拒你所想拒

关心你想要拒绝掉哪些东西,比如一个BBS论坛上拦截掉敏感词汇。

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

2.过滤器依赖于servlet容器,而拦截器不依赖于servlet容器。

3.拦截器只对action起作用,而过滤器几乎可以对所有请求起作用。

4.拦截器可以访问action上下文、值栈里的对象,而过滤器不能。

5.在action的生命周期里,拦截器可以多起调用,而过滤器只能在容器初始化时调用一次。

现在发现和自己的想法差不多,核心一句话“拒你所相拒”!

声明和使用拦截器

搞清楚概念和用途后,就该尝试一下了。我一直很讨厌书大而全,啥都给你讲,生怕你不知道乾隆的第42个娘娘的外婆的外甥女的爸爸叫啥,有必要么?我们需要将最常用的东西,其他就直接说有几种方法,其中哪两种已经不适用了,我们介绍这种,就OK了,唉….

现在开发实际上都是直接在struts.xml配置拦截器,这样就避免了在类中指定的高耦合的情况。在Struts.xml配置过滤器的格式是:

<interceptor name=”interceptorName”class=”interceptorClass /></interceptor>

实际上定义的格式与Action十分类似。如果你像向配置的拦截器传递参数你还可以在标签之中添加param标签,指定你需要传递的参数即可。

在开发中往往需要多个拦截器配合使用,这时候需要一个拦截器栈了。他的定义就是

<interceptor-stack name=”xxx”></interceptor-stack>在标签里面使用

<interceptor-ref>标签来指定拦截器。

具体怎么使用通过例子来演示吧,没有例子干看配置,总也不会太明白的,也没兴趣。

当然还有几个概念:

默认拦截器

<default-interceptor-ref name=”已经存在的拦截器或拦截器栈的名字”/>这个标签是package的子标签。

内建拦截器

我们没有配置拦截器的时候,你就已经可以获取到HHTP请求的传值了,这就是因为内建拦截器把参数拿到了存到了你可以拿到的地方。

内建拦截器就像一个工具库一样,为你提供了很多使用的东西,比如说提供文件上传功能的fileUpload啊,比如说输出Action执行时间的Timer等等等,这些内建拦截器用到了去查就行了。

下面看一看怎样自定义一个拦截器来扩展struts的功能:

首先需要实现Interceptor接口,需要实现三个方法,init、destory和interceptor。那么Struts2的AbstractInterceptor已经为我们实现了Interceptor接口,大多数情况下我们直接继承AbstractInterceptor就可以了,这个和Action接口与ActionSupport类的关系很相似。

下面是一个拦截器的实现:

package tech.youngs.Interceptor;

import com.opensymphony.xwork2.ActionInvocation;
import com.opensymphony.xwork2.interceptor.AbstractInterceptor;

public class RegInterceptor extends AbstractInterceptor{
    private static final long serialVersionUID = 1L;

@Override
    public String intercept(ActionInvocation arg0) throws Exception {
        // TODO Auto-generated method stub
        System.out.println("拦截器开始工作");
        String result = arg0.invoke();
        System.out.println("拦截器结束工作");
        return result;
    }

}

Action的代码其实没什么特别的就不贴了,这里贴出struts.xml的配置代码:

<interceptors>
            <interceptor name="register" class="tech.youngs.Interceptor.RegInterceptor"/>
        </interceptors>
        <action name="reg" class="tech.youngs.Action.RegisterAction">
            <result name="success">/WEB-INF/jsp/success.jsp</result>
            <result name="input">/WEB-INF/jsp/reg.jsp</result>
            <interceptor-ref name="defaultStack" />
            <interceptor-ref name="register" />
        </action>

特别注意 是<interceptors>标签里面定义着拦截器 在action里面使用<interceptor-ref>引用就行了。在写代码的时候还出现了一个错误,就是引用的定义的拦截器的name不相同了,给我报404的页面,现在体会着struts报了404绝壁是配置文件除了问题,慢慢找就行了 注意一下什么name想不想同啊 这一类的问题。

拦截器深入

上面只介绍了拦截器的原理,还不知道内部是怎么运行的,输出了一下args.invoke 控制台显示了input也就是不成功的时候的字符串。这个东西我觉得网上的文章说的很好:

invocation.invoke() 就是通知struts2接着干下面的事情

比如 调用下一个拦截器 或 执行下一个Action

就等于退出了你自己编写的这个interceptor了

1. 如果拦截器堆栈中还有其他的Interceptor,那么invocation.invoke()将调用堆栈中下一个Interceptor的执行。
2. 如果拦截器堆栈中只有Action了,那么invocation.invoke()将调用Action执行。

特别注意,在使用自定义拦截器的时候,必须引用struts2自带的拦截器缺省堆栈defaultStack,不然会出错。

在实际的开发过程中,实际很少会对整个Action去拦截,可能只需要对某几个方法去进行验证之类的工作,那么struts提供了一种过滤方法的拦截器,这个拦截器与普通拦截器的唯一不同就是,继承了MethodFilterIntercepter,这个类已经继承了AbstractInterceptor,它重写了intercept方法,还提供了doIntercept的抽象方法供用户实现。

其实MethodFilterIntercepter与普通的拦截器的实现代码没什么区别。那么怎么实现过滤到需要拦截的方法呢——struts.xml继续看….

<intercepter-ref name=”xxxInterceptor”>

<param name=”executeMethods”>execute,login</param>

</intercepter-ref>

在引用自定义拦截器的时候,增加一个名为executeMethods的参数就行了,中间的方法名将不会被拦截,特别注意是executeMethods,这个在声明拦截器的时候的坑很像,就是复数,而且这种错误犯了的话会很难找的,interceptors和executeMethods。中间的方法名使用都好隔开就行了。

下面看一个比较高级的例子吧,权限控制。这个我在PHP的时候做过,思路就是库内的用户权限有单独的字段,然后他登录了权限字段会存入Session中,那么页面会判断你这个session里的权限是不是满足访问页面的最低权限,ok就进,or就出,就是这样的思路。

这里记一下ActionContext的几种获取方式:

  • 在自定义的拦截器中:使用ActionInvocation.getInvocationContext()或者使用ActionContext.getContext()。
  • 在Action类中:让拦截器注入或者使用ActionContext.getContext()。
  • 在非Action类中:让Action类传递参数、使用注入机制注入或者使用ActionContext.getContext()。注意:只有运行在request线程中的代码才能调用ActionContext.getContext(),否则返回的是null。

在上面我们看到,在自定义的拦截器中两种方式实际上是对等的。

在MVC框架里面有这样一条开发的原则,尽量不要再Controller层做过多的判断,这真的是一条比较好的法则,希望各位小伙伴们在开发的时候遵循。

那么在Struts2内也是一样的,我们不要讲权限的判断交给Action去执行,我们将权限的控制放在拦截器中去实现:

…..我都郁闷了 弄了一下午sessionMap没有值…..

求大神解答  为啥ActionContext在interceptor里面没有值呢?

struts2学习笔记 ⑤的更多相关文章

  1. Struts2学习笔记⑧

    今天是Struts2学习笔记的最后一篇文章了.用什么做结尾呢,这两天其实还学了很多东西,没有记录下,今天就查漏补缺一下. 文件上传与下载.FreeMarker以及昨天没做完的例子 文件上传与下载 文件 ...

  2. Struts2学习笔记①

    Struts2 学习笔记① 所有的程序学习都从Hello World开始,今天先跟着书做一个HW的示例. Struts2是一套MVC框架,使用起来非常方便,接触到现在觉得最麻烦的地方是配置文件.我的一 ...

  3. Struts2学习笔记NO.1------结合Hibernate完成查询商品类别简单案例(工具IDEA)

    Struts2学习笔记一结合Hibernate完成查询商品类别简单案例(工具IDEA) 1.jar包准备 Hibernate+Struts2 jar包 struts的jar比较多,可以从Struts官 ...

  4. Struts2 学习笔记(概述)

    Struts2 学习笔记 2015年3月7日11:02:55 MVC思想 Strust2的MVC对应关系如下: 在MVC三个模块当中,struts2对应关系如下: Model: 负责封装应用的状态,并 ...

  5. [struts2学习笔记] 第二节 使用Maven搞定管理和构造Struts 2 Web应用程序的七个步骤

    本文地址:http://blog.csdn.net/sushengmiyan/article/details/40303897 官方文档:http://struts.apache.org/releas ...

  6. struts2学习笔记之二:基本环境搭建

    学习struts2有一段时间了,作为一个运维人员学习的时间还是挺紧张的,写这篇文件为了方便以后复习时使用 环境: MyEclipse 10 tomcat6 jdk1.6   首先建立一个web项目,并 ...

  7. 【Struts2学习笔记-4】包含其他配置文件

    包含其他配置文件 <?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE struts PUBLI ...

  8. 【Struts2学习笔记-3】常量配置

    Struts2常量 配置Struts2常量值有3个地方,1)在struts.properties文件中配置常量:2)在web.xml文件中配置FileterDispatcher指定初始化参数来配置常量 ...

  9. struts2学习笔记(4)——数据类型转换

    回过头来看昨天的那个例子. 在昨天的例子中,只转换了一个Point类,如果想转换多个Point类怎么办呢?在昨天的例子上面做一个小的修改. 首先在input.jsp页面中修改几个输入框. <s: ...

随机推荐

  1. Win10下CISCO VPN Client无法安装解决方案

    Cisco vpn client 在Windows升级到Windows 10 之后无法正常安装使用,在这种情况下:1.先安装Dell SonicWALL Global VPN Client(GVCSe ...

  2. springMvc获取servletContext

    springMvc获取servletContext WebApplicationContext webApplicationContext = ContextLoader.getCurrentWebA ...

  3. 用 NodeJS 实现 BigPipe

    BigPipe 是 Facebook 开发的优化网页加载速度的技术.网上几乎没有用 node.js 实现的文章,实际上,不止于 node.js,BigPipe 用其他语言的实现在网上都很少见.以至于这 ...

  4. 【Zookeeper】源码分析之Watcher机制(三)之Zookeeper

    一.前言 前面已经分析了Watcher机制中的大多数类,本篇对于ZKWatchManager的外部类Zookeeper进行分析. 二.Zookeeper源码分析 2.1 类的内部类 Zookeeper ...

  5. Python内置数据类型总结

    python的核心数据类型:(很多语言之提供了数字,字符串,文件数据类型,其他形式的数据类型都以标准库的形式表示 也就是用之前需要import ) ,但是python有很多都是内置的,不需要impor ...

  6. Prim和Kruskal最小生成树

    标题: Prim和Kruskal最小生成树时 限: 2000 ms内存限制: 15000 K总时限: 3000 ms描述: 给出一个矩阵,要求以矩阵方式单步输出生成过程.要求先输出Prim生成过程,再 ...

  7. css3基础知识——回顾

    1.属性选择器 完全匹配的属性选择器 [id=article]{} 示例: <style> input[type=text]{ border: 2px solid red;} </s ...

  8. 在Window下安装Oracle

    一.Oracle下载地址 http://www.oracle.com/technetwork/database/enterprise-edition/downloads/index.html 二.解压 ...

  9. Centos 7安装oracle 11g R2问题及解决方法汇总

    自己新博客的链接:http://www.pythonsite.com/2017/02/14/centos-7%E5%AE%89%E8%A3%85oracle-11g-r2%E9%97%AE%E9%A2 ...

  10. matab plot指令和低通滤波器的响应图

    一.plot额外的四个属性模板使用 代码 % 提示 disp ('该功能练习plot额外四个属性功能'); %初始化快捷式数组 figure(); x=:pi/:*pi; y=exp(*sin(x)) ...