Struts2的靈魂——Interceptor

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 



Java代碼  收藏代碼
  1.     
  2. 1.package com.interceptor.test;    
  3. 2.    
  4. 3.import java.util.ArrayList;    
  5. 4.import java.util.Iterator;    
  6. 5.import java.util.List;    
  7. 6./**  
  8. 7. * 模擬DefaultActionInvocation  
  9. 8. *  所有的攔截器存放在一個ArrayList中  
  10. 9. *  該類應當持有攔截器數組的引用和Action的引用  
  11. 10. */    
  12. 11.public class Invocation{    
  13. 12.    private List<Interceptor> interceptors = new ArrayList<Interceptor>();    
  14. 13.    private Iterator<Interceptor> interator;    
  15. 14.    private Action action;    
  16. 15.    /**  
  17. 16.     * 初始化攔截器和action  
  18. 17.     * 用new 模擬  
  19. 18.     * 實際上Invocation是從struts.xml讀取內容,並初始化的  
  20. 19.     */    
  21. 20.    public Invocation(){    
  22. 21.        //按順序加入Interceptor    
  23. 22.        interceptors.add(new FirstInterceptor());    
  24. 23.        interceptors.add(new SecondInterceptor());    
  25. 24.        interceptors.add(new ThirdInterceptor());    
  26. 25.        interator = interceptors.iterator();    
  27. 26.        action = new Action();    
  28. 27.    }    
  29. 28.    /**  
  30. 29.     * 這是一個遞歸方法  
  31. 30.     * 方法直接或者間接地調用自身即爲遞歸。 
  32. 31.     *invoke()調用intercept(),intercept()又調用invoke()   
  33. 32.     */    
  34. 33.    public void invoke(){    
  35. 34.        Interceptor interceptor;    
  36. 35.        //若鏈表中仍有Interceptor,則調用下一個Interceptor    
  37. 36.        if(interator.hasNext()){    
  38. 37.            interceptor = interator.next();    
  39. 38.            interceptor.intercept(this);    
  40. 39.        }    
  41. 40.        //鏈表中沒有Interceptor了,則調用Action    
  42. 41.        else{    
  43. 42.            action.execute();    
  44. 43.        }    
  45. 44.    }    
  46. 45.}    


Interceptor.java 
Java代碼  收藏代碼
  1. 1.package com.interceptor.test;    
  2. 2.//模擬com.opensymphony.xwork2.interceptor.Interceptor接口    
  3. 3.//所有攔截器都應該實現該接口或者繼承自Interceptor的子類    
  4. 4.public interface Interceptor {    
  5. 5.    //這是攔截器類的最重要的方法    
  6. 6.    //invocation用於存儲攔截器鏈表    
  7. 7.    public void intercept(Invocation invocation);    
  8. 8.}    
  9.    


FirstInterceptor.java 
Java代碼  收藏代碼
  1.     
  2. 1.package com.interceptor.test;    
  3. 2.//第一個攔截器    
  4. 3.public class FirstInterceptor implements Interceptor{    
  5. 4.    @Override    
  6. 5.    public void intercept(Invocation invocation) {    
  7. 6.        //向控制輸出信息,來模擬action調用前的處理工作    
  8. 7.        System.out.println("first interceptor -->be called");    
  9. 8.        //回調DefaultAcctionInvocation的方法    
  10. 9.        invocation.invoke();    
  11. 10.        //模擬action調用後的處理工作    
  12. 11.        System.out.println("first interceptor -->return");    
  13. 12.    }    
  14. 13.}    
  15.    

SecondInterceptor.java 
Java代碼  收藏代碼
  1.    
  2. 1.package com.interceptor.test;    
  3. 2.//第二個攔截器    
  4. 3.public class SecondInterceptor implements Interceptor{    
  5. 4.    @Override    
  6. 5.    public void intercept(Invocation invocation) {    
  7. 6.        System.out.println("Second interceptor -->be called");    
  8. 7.        invocation.invoke();    
  9. 8.        System.out.println("Second interceptor -->return");    
  10. 9.    }    
  11. 10.}    
  12.    

ThirdInterceptor.java 
Java代碼  收藏代碼
  1.    
  2. 1.package com.interceptor.test;    
  3. 2.//第三個攔截器    
  4. 3.public class ThirdInterceptor implements Interceptor{    
  5. 4.    @Override    
  6. 5.    public void intercept(Invocation invocation) {    
  7. 6.        System.out.println("Third interceptor -->be called");    
  8. 7.        invocation.invoke();    
  9. 8.        System.out.println("Third interceptor -->return");    
  10. 9.    }    
  11. 10.}    
  12.    

Action.java 
Java代碼  收藏代碼
  1. package com.interceptor.test;  
  2.   
  3. public class Action {  
  4.     public String execute(){  
  5.         System.out.println("Action-->execute");  
  6.         return "success";  
  7.     }  
  8. }  

Main.java 
Java代碼  收藏代碼
  1. 1.package com.interceptor.test;    
  2. 2.//用於啓動模擬程序    
  3. 3.//模擬StrutsActionProxy的execute()方法    
  4. 4.public class Main {    
  5. 5.    // 創建Invocation,並調用其invoke()方法    
  6. 6.    public static void main(String[] args) {    
  7. 7.        new Invocation().invoke();    
  8. 8.    }    
  9. 9.}    
  10.    


控制檯輸出結果爲: 
Java代碼  收藏代碼
  1.    
  2. 1.first interceptor -->be called    
  3. 2.Second interceptor -->be called    
  4. 3.Third interceptor -->be called    
  5. 4.Action-->execute    
  6. 5.Third interceptor -->return    
  7. 6.Second interceptor -->return    
  8. 7.first interceptor -->return    
  9.    


相信看到輸出結果之後,不用過多的解釋,你也會對Interceptor的工作原理有更具體的瞭解了。 

補充:本文中之所以只談遞歸,不談模式,是爲了讓讀者更深刻更具象的瞭解底層原理。 
發佈了6 篇原創文章 · 獲贊 4 · 訪問量 2萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章