拦截器初探

昨天临睡觉之前看了看拦截器,也在昨天的学习笔记里面胡诌诌了几句,今天就来好好的会会拦截器这个东西。实际上拦截器是一种模块实现的机制<起码我是这么体会的>(至于说书里面说体现了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. ASP.NET MVC中使用异步控制器

    线程池 一直想把项目改写成异步,但是ASP.NETMVC3下写的过于繁琐,.NET 4.5与ASP.NET MVC下代码写起来就比较简单了, MS好像也一直喜欢这样搞,每一个成熟的东西,都要演变好几个 ...

  2. Web浏览器兼容性测试工具如何选择

    对于前端开发工程师来说,网页兼容性测试工程师而言,确保代码在各种主流浏览器的各个版本中都能正常工作是件很费时的事情,幸运的是,有很多优秀的工具可以帮助测试浏览器的兼容性,领测软件测试网向您推荐12款很 ...

  3. 一步一步Asp.Net MVC系列_权限管理设计

    http://www.cnblogs.com/mysweet/archive/2012/07/26/2610793.html

  4. SpringMVC 前端获得定义JSON对象的方法

    SpringMVC 前端获得定义JSON对象的方法: 可以使用map进行对象的创建,这样就会解析成键值对,不需要为前端专门定义对象.

  5. Word常用实用知识3

    纯手打,可能有错别字,使用的版本是office Word 2013 转载请注明出处 http://www.cnblogs.com/hnnydxgjj/p/6322813.html,谢谢. 分页符分页 ...

  6. 在C++中反射调用.NET(三)

    在.NET与C++之间传输集合数据 上一篇<在C++中反射调用.NET(二)>中,我们尝试了反射调用一个返回DTO对象的.NET方法,今天来看看如何在.NET与C++之间传输集合数据. 使 ...

  7. HTML__post 和 get区别【URL】

    一.get和post的区别: 表单提交中get和post方式的区别有5点 1.get是从服务器上获取数据,post是向服务器传送数据. 2.get是把参数数据队列加到提交表单的ACTION属性所指的U ...

  8. 读书笔记 effective c++ Item 2 尽量使用const,枚举(enums),内联(inlines),不要使用宏定义(define)

    这个条目叫做,尽量使用编译器而不要使用预处理器更好.#define并没有当作语言本身的一部分. 例如下面的例子: #define ASPECT_RATIO 1.653 符号名称永远不会被编译器看到.它 ...

  9. CSS3知识点整理(四)----布局样式及其他

    包括CSS3多列布局样式.Flexbox伸缩布局.盒子模型等.重点介绍了Flexbox伸缩布局的各种属性用法. 一.多列布局 为了能在Web页面中方便实现类似报纸.杂志那种多列排版的布局,W3C特意给 ...

  10. SQL语句的优化建议

    重中之重---语句执行顺序   我们先看看语句的执行顺序 如果我没记错这是<SQL SERVER 2005技术内幕--查询>这本书的开篇第一章第一节.书的作者也要让读者首先了解语句是怎么样 ...