套话


相信非常多人都用过 Struts2 了,当然,对 Struts2 的原理也都比較了解。之前在一个项目中就已经用到了,当初的理解也不过局限在应用的层面上,对于更深层次的原理、机制,了解的并非非常多。如今回过头来,再看 Struts2 的拦截器,相比之前的理解,又别有还有一番滋味。


理解


Struts2 的拦截器,英文名为 Interceptor ,至于为什么中文要翻译为拦截器,我想这一定是有原因的,肯定不是一拍脑门,就叫拦截器了(它必然有什么含义在里边)。从字面的意思,就是在发送请求的时候,有一个什么东西把这个请求给拦截了,给挡下了,目的就是为了在请求之前、之后运行自己的方法(勿喷,大白话,仅供理解)。

拦截器能够动态地拦截发送到指定 Action 的请求,通过拦截机制,我们能够在 Action 运行的前后插入某些代码。通过这样的方式,就能够把多个 Action 中须要反复指定的代码提取出来,放在拦截器里定义,从而提供更好的代码重用性。


意义


那么,拦截器有什么存在的必要呢?这个问题也许大家都没有想过,仅仅知道 Struts2 的拦截器好用,仅仅知道 Struts2 的拦截器怎么用而已。谈意义之前,首先讲一个规则,相信大家早就听说过了,事实上一点也不新奇 —— DRY 规则,就是所谓的“Don't  Repeat Yourself”,意思大家都明确,就是“不要写反复的代码”。

拦截器的意义(之中的一个)就在于此,能够这样理解:拦截器是对调用方法的改进。未使用拦截器时,代码中往往会须要显式的调用目标方法。假设把公共的部分抽象出来,定义成拦截器里的方法,就能够避免这种耦合,直接由系统来调用。


实现原理


一般的说,拦截器都是通过代理的方式调用的。当请求到达 Struts2 的 ServletDispatcher 时,Struts2 会查找配置文件,并依据其配置实例化相对的拦截器对象,然后组成一个列表,最后一个一个地调用列表中的拦截器。

从本质上说,拦截器的实现主要是基于动态代理技术。用户发送 Action 请求时,系统会为 Action 创建一个代理对象,由这个代理对象调用 Action 的 execute() 或指定的方法,并在 struts.xml 中查找与该 Action 相应的拦截器。假设有相应的拦截器,就在 Action 的方法运行前(后)调用这些拦截器;假设没有相应的拦截器则运行 Action
的方法。当中系统对于拦截器的调用,是通过ActionInvocation来实现的。


代码演示


以下以 JDK动态代理为例,通过一个普通的 Java 程序,介绍怎样调用拦截器的方法,给大家做一个演示,希望能给你带来帮助。

Dog 接口


<span style="font-family:Microsoft YaHei;">public interface Dog {
// info 方法声明
public void info();
// run 方法声明
public void run();
}</span>
上面接口里简单定义了两个方法,因为 JDK 动态代理仅仅能对实现了接口的实例来生成代理。因此必须提供一个接口。


Dog 实现

<span style="font-family:Microsoft YaHei;">public class DogImpl implements Dog {
@Override
public void info() {
System.out.println("我是一仅仅小小狗");
} @Override
public void run() {
System.out.println("我奔跑迅速");
}
}</span>

该 Dog 的实现类只为每一个方法提供了一个简单实现,不过做了简单的打印。


拦截器类

<span style="font-family:Microsoft YaHei;">public class DogIntercepter {
// 第一个拦截器方法
public void method1() {
System.out.println("********** 通用模拟方法一 *********");
} // 第二个拦截器方法
public void method2() {
System.out.println("********** 通用模拟方法二 *********");
}
}</span>
事实上,拦截器也是一个普通的 Java 类,之所以称为拦截器,主要是由于他的行为而命名的。


ProxyHandler 类


<span style="font-family:Microsoft YaHei;">public class ProxyHandler implements InvocationHandler {
// 需被代理的目标对象
private Object target;
// 创建拦截器实例
DogIntercepter di = new DogIntercepter();
// 运行代理的目标方法时,该invoke方法会被自己主动调用
@Override
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
Object result = null;
// 假设被调用方法的方法名为info
if ("info".equals(method.getName())) {
// 调用拦截器方法 1
di.method1();
result = method.invoke(target, args);
// 调用拦截器方法 2
di.method2();
} else {
result = method.invoke(target, args);
}
return result;
} // 用于设置传入目标对象的方法
public void setTarget(Object target) {
this.target = target;
}
}</span>

该类是一个代理类,它须要实现 InvocationHandler接口,该接口是 JDK反射体系里的一个接口,它能够动态调用目标对象的方法。


代理工厂类


系统还须要提供一个代理工厂,代理工厂的主要作用就是依据目标对象生成一个代理对象。

Proxy.newProxyInstance() 方法依据接口数组动态创建代理类实例,接口数组通过 object.getClass().getInterfaces() 方法获得,创建的代理类是 JVM 在内存中动态创建,该类实现传入參数里接口数组中的所有接口。


从上面能够看出,代理工厂负责依据目标对象和相应的拦截器生成新的代理对象,代理对象里的方法是目标方法和拦截器方法的组合。正式通过这样的方式,实现了在目标方法之前或之后,自己主动调用拦截器方法的目的。


主程序

<span style="font-family:Microsoft YaHei;">public class TestDog {
/**
* @param args
*/
public static void main(String[] args) {
// 创建一个Dog实例,该实例将被作为代理的目标对象
Dog targetObject = new DogImpl();
Dog dog = null;
// 以目标对象创建代理
Object proxy = MyProxyFactory.getProxy(targetObject);
if (proxy instanceof Dog) {
dog = (Dog) proxy;
}
// 測试代理的方法
dog.info();
dog.run();
}
}</span>

效果图





结束语


这篇文章,是用最简单的文字和演示样例,来演示了 Struts2 拦截器的实现原理,当然,写的还有非常多瑕疵,欢迎各位大神拍砖。By the way!通过这篇小文章,你是否想到了 Spring 的 AOP ? Struts2 的拦截器 和 Spring 的 AOP 有什么关系呢?你是否已经想到了。事实上,Struts2
的拦截器 就是基于 AOP 的思想实现的,仅仅只是,那会的 AOP 还没有提出比較明白的概念罢了。也能够说,拦截器就是 AOP 实现的前身。当然,兴许的 AOP 功能更强大一些。

谈谈 Struts2 的拦截器的更多相关文章

  1. 简单理解Struts2中拦截器与过滤器的区别及执行顺序

    简单理解Struts2中拦截器与过滤器的区别及执行顺序 当接收到一个httprequest , a) 当外部的httpservletrequest到来时 b) 初始到了servlet容器 传递给一个标 ...

  2. struts2总结六: Struts2的拦截器

    一.Struts2的系统结构图

  3. Struts2使用拦截器完成权限控制示例

    http://aumy2008.iteye.com/blog/146952 Struts2使用拦截器完成权限控制示例 示例需求:    要求用户登录,且必须为指定用户名才可以查看系统中某个视图资源:否 ...

  4. Struts2自定义拦截器Interceptor以及拦截器登录实例

    1.在Struts2自定义拦截器有三种方式: -->实现Interceptor接口 public class QLInterceptorAction implements Interceptor ...

  5. struts2之拦截器

    1. 为什么需要拦截器 早期MVC框架将一些通用操作写死在核心控制器中,致使框架灵活性不足.可扩展性降低, Struts 2将核心功能放到多个拦截器中实现,拦截器可自由选择和组合,增强了灵活性,有利于 ...

  6. Struts2【拦截器】就是这么简单

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

  7. 【struts2】拦截器基础

    1)拦截器是什么? 拦截器(Interceptor)是Struts2最强大的特性之一,它是一种可以让你在Action执行之前和Result执行之后进行一些功能处理的机制.来回顾一下官方给出的Strut ...

  8. JavaWeb框架_Struts2_(三)---->Struts2的拦截器

    2. Struts2的拦截器(使用拦截器实现权限控制) 2.1 拦截器的概述 拦截器是Struts2的核心组成部分,它可以动态的拦截Action调用的对象,类似与Servlet中的过滤器.Struts ...

  9. (转)Struts2的拦截器

    http://blog.csdn.net/yerenyuan_pku/article/details/68648101 Struts2的拦截器 拦截器的概述 拦截器,在AOP(Aspect-Orien ...

随机推荐

  1. bzoj1055: [HAOI2008]玩具取名(dp)

    1055: [HAOI2008]玩具取名 题目:传送门 简要题意: 就是固定四个字母,给出这四个字母分别可以由哪两个字母组成,然后在给你一个字符串,要求把这个字符串还原成原始的四个字母的其中一个. 题 ...

  2. PHP str_replace() 和str_ireplace()函数

    PHP str_replace() 和str_ireplace()函数 实例 把字符串 "Hello world!" 中的字符 "world" 替换为 &quo ...

  3. P 值(p value)与统计检验

    P 值是最常用的一个统计学指标,几乎统计软件输出结果都有P值. 统计学的观点,超过一定基准(比如 5%,其实是低于5%),就不能简单地认为这是偶然事件了,而是受到了外在的影响. 一般而言,为了确定从样 ...

  4. POJ1284 Primitive Roots (原根)

    题目链接:http://poj.org/problem?id=1284 题目描述: 题目大意: 一个质数原根的个数 题解: 结论题 一个数n的原根的个数等于$\varphi(\varphi(n))$ ...

  5. CUDA笔记(八)

    今天真正进入了攻坚期.不光是疲劳,主要是遇到的问题指数级上升,都是需要绕道的. 以visual profile来说,刚刚发现自己还没使用过. http://bbs.csdn.net/topics/39 ...

  6. sublime text3之修改注释颜色

    在用sublime text3编写Python2代码时总觉得注释颜色太浅了, 看起来吃力,于是就尝试去修改,和sublime text2不同, sublime text3的主题配置文件在Sublime ...

  7. Mojo Associated Interfaces

    Mojo Associated Interfaces yzshen@chromium.org 02/22/2017 Background Before associated interfaces ar ...

  8. 使用WinNTSetup安装win10时提示efi part有红叉(win10安装UEFI系统安装)

    1.装载ImDisk虚拟磁盘 2.格式化硬盘 *格式化时注意”创建新ESP分区 3.使用 WinNTSetup 选择win10安装程序 *1. “BOOTMGR PBR "后有感叹号不用管, ...

  9. CSS浏览器兼容问题集(一)

    CSS对浏览器的兼容性有时让人非常头疼,也许当你了解其中的技巧跟原理,就会认为也不是难事,从网上收集了IE7,6与Fireofx的兼容性处理方法并整理了一下.对于web2.0的过度,请尽量用xhtml ...

  10. Android——4.2 - 3G移植之路之 APN (五)

    APN,这东西对于刚接触的人来说并非那么好理解.对于3G移植上网不可缺少,这里记录一下. 撰写不易,转载请注明出处:http://blog.csdn.net/jscese/article/detail ...