上圖提供了struts2的執行流程。如下:
1:從客戶端發出請求(HTTPServletRequest)。
2:請求經過各種過濾器(filter),注:一般情況下,如SiteMesh等其他過濾器要放在核心控制器FilterDispatcher之前,也就是web.xml中配置的filter-mapping在
StrutsPrepareAndExecuteFilter之前. 在執行完了所有的過濾器的doFilter方法之后,核心控制器FilterDispatcher會清空ActionContext。所以, 其中ActionContextCleanUp作用是在doFilter里設置了一個計數器,使后續的filter不會清空ActionContext,最后執行完流程后由ActionContextCleanUp清空。如果沒有ActionContextCleanUp,如果涉及到struts2中的如valuestack中的數據時會有可能得不到想要的數據。
3:經過各種過濾器后,到達核心控制器FilterDispatcher,被調用后,通過struts.xml配置文件中Action標簽中的映射來確定調用的Action方法,
4:當確定了調用的Action之后會找到反射生成的指定Action的代理對象(ActionProxy),
5:ActionProxy會通過配置文件信息找到指定的Action,
6:然后會經過系統和自定義攔截器棧,攔截器中都有重寫一個public String doIntercept(ActionInvocation invocation) throws Exception{}的方法,
攔截器中會通過判斷有執行invocation.invoke()返回一個字符串,來連接到下一個攔截器或者到達執行Action。
7:action執行完畢后,會返回一個字符串,該字符串與配置文件Action中result的name屬性相對應,將處理得到的數據封裝到此視圖來,
8:在依次出了攔截器棧之后,將數據響應(HttpServletResponse)到客戶端。其中在經過ActionContextCleanUp時候會清空ActionContext。
由上面執行流程可以看出Action與servlet不同:
Servlet是單實例多線程的,而Action是多實例多線程的。因為多實例,所有每個請求會產生不同的Action和ActionContext對象,因此線程是安全的。同時因為Action是多實例的,所以Action中可以有成員變量,因為多實例不會公用。而Servlet是單實例多線程,所以一般情況下不會定義成員變量,因為共用同一個成員變量可能出現線程安全的問題。