精华帖 (0) :: 良好帖 (12) :: 新手帖 (5) :: 隐藏帖 (0)
|
|
---|---|
作者 | 正文 |
发表时间:2012-03-07
最后修改:2012-03-19
1.什么是拦截器: 拦截器是动态拦截Action调用的对象。它提供了一种机制使得开发者可以定义action执行之前或之后执行的代码,也可以在一个action执行前阻止其执行。 2.AOP: 提到拦截器,我们不得不提到AOP. AOP(Aspect-Oriented Programming)译为:“面向切面编程”或者“面向方面编程”。利用AOP可以对业务逻辑的各个部分进行隔离,从而使得业务逻辑各部分之间的耦合度降低,提高程序的可重用性,同时提高了开发的效率。拦截器的就是实现AOP的一种策略。 拦截器的工作原理简略图: 3.拦截器的作用: 我们可以用Interceptor在Action的方法执行之前或者之后做一些处理,struts的核心功能正是由拦截器来实现的,比如捕获异常、数据校验、安全审查等等。 4.拦截器的工作原理: Interceptor Stack(拦截器堆)中有顺序的存储着多个Interceptor,他们联接成链状,然后按照添加的顺序,依次调用。这里用到了递归调用,我认为这是设计者的聪明之处。 DefaultActionInvocation类持有拦截器链的引用,以及action的引用,是控制递归调用的重要类。 关于递归更深入的探讨,请猛击:http://candy-code.iteye.com/blog/1443427 下面我们就来模拟一下Interceptor的工作原理 5.Interceptor模拟: Invocation.java 1.package com.interceptor.test; 2. 3.import java.util.ArrayList; 4.import java.util.Iterator; 5.import java.util.List; 6./** 7. * 模拟DefaultActionInvocation 8. * 所有的拦截器存放在一个ArrayList中 9. * 该类应当持有拦截器数组的引用和Action的引用 10. */ 11.public class Invocation{ 12. private List<Interceptor> interceptors = new ArrayList<Interceptor>(); 13. private Iterator<Interceptor> interator; 14. private Action action; 15. /** 16. * 初始化拦截器和action 17. * 用new 模拟 18. * 实际上Invocation是从struts.xml读取内容,并初始化的 19. */ 20. public Invocation(){ 21. //按顺序加入Interceptor 22. interceptors.add(new FirstInterceptor()); 23. interceptors.add(new SecondInterceptor()); 24. interceptors.add(new ThirdInterceptor()); 25. interator = interceptors.iterator(); 26. action = new Action(); 27. } 28. /** 29. * 这是一个递归方法 30. * 方法直接或者间接地调用自身即为递归。 31. *invoke()调用intercept(),intercept()又调用invoke() 32. */ 33. public void invoke(){ 34. Interceptor interceptor; 35. //若链表中仍有Interceptor,则调用下一个Interceptor 36. if(interator.hasNext()){ 37. interceptor = interator.next(); 38. interceptor.intercept(this); 39. } 40. //链表中没有Interceptor了,则调用Action 41. else{ 42. action.execute(); 43. } 44. } 45.} Interceptor.java 1.package com.interceptor.test; 2.//模拟com.opensymphony.xwork2.interceptor.Interceptor接口 3.//所有拦截器都应该实现该接口或者继承自Interceptor的子类 4.public interface Interceptor { 5. //这是拦截器类的最重要的方法 6. //invocation用于存储拦截器链表 7. public void intercept(Invocation invocation); 8.} FirstInterceptor.java 1.package com.interceptor.test; 2.//第一个拦截器 3.public class FirstInterceptor implements Interceptor{ 4. @Override 5. public void intercept(Invocation invocation) { 6. //向控制输出信息,来模拟action调用前的处理工作 7. System.out.println("first interceptor -->be called"); 8. //回调DefaultAcctionInvocation的方法 9. invocation.invoke(); 10. //模拟action调用后的处理工作 11. System.out.println("first interceptor -->return"); 12. } 13.} SecondInterceptor.java 1.package com.interceptor.test; 2.//第二个拦截器 3.public class SecondInterceptor implements Interceptor{ 4. @Override 5. public void intercept(Invocation invocation) { 6. System.out.println("Second interceptor -->be called"); 7. invocation.invoke(); 8. System.out.println("Second interceptor -->return"); 9. } 10.} ThirdInterceptor.java 1.package com.interceptor.test; 2.//第三个拦截器 3.public class ThirdInterceptor implements Interceptor{ 4. @Override 5. public void intercept(Invocation invocation) { 6. System.out.println("Third interceptor -->be called"); 7. invocation.invoke(); 8. System.out.println("Third interceptor -->return"); 9. } 10.} Action.java package com.interceptor.test; public class Action { public String execute(){ System.out.println("Action-->execute"); return "success"; } } Main.java 1.package com.interceptor.test; 2.//用于启动模拟程序 3.//模拟StrutsActionProxy的execute()方法 4.public class Main { 5. // 创建Invocation,并调用其invoke()方法 6. public static void main(String[] args) { 7. new Invocation().invoke(); 8. } 9.} 控制台输出结果为: 1.first interceptor -->be called 2.Second interceptor -->be called 3.Third interceptor -->be called 4.Action-->execute 5.Third interceptor -->return 6.Second interceptor -->return 7.first interceptor -->return 相信看到输出结果之后,不用过多的解释,你也会对Interceptor的工作原理有更具体的了解了。 补充:本文中之所以只谈递归,不谈模式,是为了让读者更深刻更具象的了解底层原理。 声明:ITeye文章版权属于作者,受法律保护。没有作者书面许可不得转载。
推荐链接
|
|
返回顶楼 | |
发表时间:2012-03-09
通俗易懂,原来递归调用就这么回事,不错
|
|
返回顶楼 | |
发表时间:2012-03-09
顺便请问下 LZ, struts2 的 拦截器 和 servlet标准中的 过滤器 在设计是是否相似 ? 都是在 某个过滤器链中 调用下一个链, 只是前者递归,后者顺序执行。
|
|
返回顶楼 | |
发表时间:2012-03-09
最后修改:2012-03-09
beyondyuefei 写道 顺便请问下 LZ, struts2 的 拦截器 和 servlet标准中的 过滤器 在设计是是否相似 ? 都是在 某个过滤器链中 调用下一个链, 只是前者递归,后者顺序执行。
Filter(过滤器)和Interceptor在设计上非常类似,都运用了递归的思想。 Filter接口最重要的方法是 doFilter(ServletRequest req, ServletResponse res, FilterChain chain){},其中chain就是过滤器链, Filter的子类StrutsPrepareAndExecuteFilter在doFilter()中有这样一段代码: if (!handled) { chain.doFilter(request, response); } else { execute.executeAction(request, response, mapping); } 可以看出,和Interceptor非常类似。 |
|
返回顶楼 | |
发表时间:2012-03-09
写得不错 说明楼主对原理掌握得不错
|
|
返回顶楼 | |
发表时间:2012-03-09
写的通俗易懂,lz对原理讲的很好
|
|
返回顶楼 | |
发表时间:2012-03-09
Candy_Code 写道 beyondyuefei 写道 顺便请问下 LZ, struts2 的 拦截器 和 servlet标准中的 过滤器 在设计是是否相似 ? 都是在 某个过滤器链中 调用下一个链, 只是前者递归,后者顺序执行。
Filter(过滤器)和Interceptor在设计上非常类似,都运用了递归的思想。 Filter接口最重要的方法是 doFilter(ServletRequest req, ServletResponse res, FilterChain chain){},其中chain就是过滤器链,Filter的子类StrutsPrepareAndExecuteFilter在doFilter()中有这样一段代码: if (!handled) { chain.doFilter(request, response); } else { execute.executeAction(request, response, mapping); } 可以看出,和Interceptor非常类似。 “其中chain就是过滤器链,Filter的子类”???谁说的?jdk API里可不是子类,虽然说设计成子类有更好的扩展,因为可以往里面直接添加FilterChain,但是事实就是没有。 |
|
返回顶楼 | |
发表时间:2012-03-09
这个叫递归吗?command模式才对
|
|
返回顶楼 | |
发表时间:2012-03-09
whiletrue 写道 这个叫递归吗?command模式才对
对,设计模式理解的很深刻。 |
|
返回顶楼 | |
发表时间:2012-03-09
新手来学习下,还要再看两遍呢
|
|
返回顶楼 | |