前面說完了Spring、Hibernate,很自然今天輪到struts了。struts的核心原理就是通過攔截器來處理客戶端的請求,經過攔截器一系列的處理後,再交給Action。下面先看看struts官方的工作原理圖:
圖1 struts原理圖
簡單分析一下:首先客戶端發來HttpServletRequest請求,傳遞給FilerDispatcher(ActionMapper是訪問靜態資源(struts的jar檔案等)時用的,平時很少用),然後FilerDispatcher會為我們建立一個ActionProxy,ActionProxy會通過ConfigurationManager獲得struts.xml檔案中的資訊,ActionProxy擁有一個ActionInvocation例項,通過呼叫ActionInvocation的invoke()方法,來挨個處理Interceptor,最後處理Action,接著Result返回,再逆序經過Interceptor,最後得到HttpServletResponse返回給客戶端。
如果不太明白呢,那就看看下面這張時序圖,也許你就懂了:
圖2 struts原理時序圖
上面的時序圖邏輯就比較清晰了,我就不過多解釋了。看完struts的原理圖,我們還是需要通過程式碼來進一步瞭解它具體是怎麼實現的。首先,我們需要一個ActionInvocation:
package com.tgb.struts; import java.util.ArrayList; import java.util.List; public class ActionInvocation { List<Interceptor> interceptors = new ArrayList<Interceptor>(); int index = -1; Action a = new Action(); public ActionInvocation() { this.interceptors.add(new FirstInterceptor()); this.interceptors.add(new SecondInterceptor()); } public void invoke() { index ++; if(index >= this.interceptors.size()) { a.execute(); }else { this.interceptors.get(index).intercept(this); } } }
我們實現的ActionInvocation是將Interceptor寫在裡面的,但實際上是通過反射載入的,原理同之前寫的Spring與Hibernate的部落格,相同的程式碼就不在這裡佔用篇幅了,也沒啥意思。不知道怎麼實現的朋友請檢視前面幾篇部落格。
接下來是我們的Interceptor介面以及兩個簡單的實現:
package com.tgb.struts; public interface Interceptor { public void intercept(ActionInvocation invocation) ; } package com.tgb.struts; public class FirstInterceptor implements Interceptor { public void intercept(ActionInvocation invocation) { System.out.println("FirstInterceptor Begin..."); invocation.invoke(); System.out.println("FirstInterceptor End..."); } } package com.tgb.struts; public class SecondInterceptor implements Interceptor { public void intercept(ActionInvocation invocation) { System.out.println("SecondInterceptor Begin..."); invocation.invoke(); System.out.println("SecondInterceptor End..."); } }
然後就是我們的Action:
package com.tgb.struts; public class Action { public void execute() { System.out.println("Action Run..."); } }
最後是我們的客戶端呼叫:
package com.tgb.struts; public class Client { public static void main(String[] args) { new ActionInvocation().invoke(); } }
差點忘了,還有我們最後的執行結果:
FirstInterceptor Begin...
SecondInterceptor Begin...
Action Run...
SecondInterceptor End...
FirstInterceptor End...
通過上面的執行結果,我們可以很清楚的看到,請求來的時候會按照順序被所有配置的攔截器攔截一遍,然後返回的時候會按照逆序再被攔截器攔截一遍。這跟資料結構中的“棧”非常類似(FIFO-先進先出),資料結構我不太懂,也許這樣比喻有些不妥。各位根據自己的認識理解吧。
最近一直在研究這三大框架,折騰半天它們都離不開集合,離不開反射。其實它們道理都是想通的,搞懂一個,其他的也就很好懂了。等著吧,早晚我們們自己寫一個更好用的。