攔截器是動態攔截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.}
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.}
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.}
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.}
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.}
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";
- }
- }
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.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
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的工作原理有更具體的瞭解了。
補充:本文中之所以只談遞歸,不談模式,是爲了讓讀者更深刻更具象的瞭解底層原理。