菜鳥學SSH(十六)——Struts2內部是如何工作的

劉水鏡發表於2014-07-31

前面說完了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-先進先出),資料結構我不太懂,也許這樣比喻有些不妥。各位根據自己的認識理解吧。

最近一直在研究這三大框架,折騰半天它們都離不開集合,離不開反射。其實它們道理都是想通的,搞懂一個,其他的也就很好懂了。等著吧,早晚我們們自己寫一個更好用的。


相關文章