1)前提條件html
在講解流程以前,假設咱們已經創建了的一個名爲strutsDeepen的web工程,該工程僅僅實現了簡單的用戶登錄與歡迎界面。具體的實現爲:前端
- 在web.xml中配置了Struts2的過濾器
- 寫了一個Action類,名稱爲loginAction
- 在struts.xml中配置了這個Action類
- 寫了兩個頁面,一個是登陸頁面,一個是歡迎頁面
只作了這麼點事情,就能夠在Struts2的幫助下順利完成功能調用,那麼Struts2內部是怎麼運行的呢?逐步來根據系統架構圖進行分析。web
2)運行流程緩存
- 當用戶提交登陸請求後,請求的URL爲:「/strutsDeepen/loginAction.action」,請求會被Tomcat服務器接收到,Tomcat服務器會根據請求URL中的web上下文,也就是「/strutsDeepen」,來選擇處理這個請求的Web應用,那就是由strutsDeepen這個web工程來處理這個請求。
- Web容器會去讀取strutsDeepen這個工程的web.xml,在web.xml中進行匹配,發現後綴爲「.action」的請求,由struts2這個過濾器來進行處理,根據Filter的配置,找到實際的類爲FilterDispatcher。
-
Web容器會獲取FilterDispatcher這個類的實例,而後回調doFilter方法,進行真正的處理。FilterDispatcher做爲前端控制器,是整個Struts2的調度中心。服務器
注意:在架構圖上,能夠看到有三個過濾器層次,分別是ActionContextCleanUp、SiteMesh等其餘過濾器和FilterDispatcher。這三個層次中,ActionContextCleanUp和FilterDispatcher是Struts2的過濾器,而SiteMeshSiteMesh等其餘過濾器不是。架構
FilterDispatcher是任何一個Struts2應用都須要配置的,通常出如今過濾器鏈的最後;若是在FilterDispatcher前出現瞭如SiteMesh這種特殊的過濾器,還必須在SiteMesh前引用Struts2的ActionContextCleanUp過濾器。app
在前面的strutsDeepen中,並無出現SiteMesh這種特殊的過濾器,因此只須要引用FilterDispatcher就能夠了。spa
- FilterDispatcher將請求轉發給ActionMapper。ActionMapper負責識別當前的請求是否須要Struts2作出處理。
- ActionMapper告訴FilterDispatcher,須要處理這個請求,FilterDispatcher會中止過濾器鏈之後的部分,因此一般狀況下:FilterDispatcher應該出如今過濾器鏈的最後。而後創建一個ActionProxy對象,這個對象做爲Action與xwork之間的中間層,會代理Action的運行過程。
- ActionProxy對象剛被建立出來的時候,並不知道要運行哪一個Action,它手裏只有從FilterDispatcher中拿到的請求的URL。這時候,它去向ConfigurationManager詢問到底要運行哪一個Action。某個特定的URL由哪一個Action響應由誰負責,定義在什麼地方呢?沒錯,在struts.xml裏面。而ConfigurationManager就是負責讀取並管理struts.xml的,能夠簡單的理解爲ConfigurationManager是struts.xml在內存中的映像。在服務器啓動的時候,ConfigurationManager會一次性的把struts.xml中的全部信息讀到內存裏,並緩存起來,以保證ActionProxy拿着來訪的URL向他詢問要運行哪一個Action的時候,就能夠直接匹配、查找並回答了。
-
ActionProxy拿到了運行哪一個Action、相關的攔截器以及全部可能使用的result信息,就能夠着手創建ActionInvocation對象了,ActionInvocation對象描述了Action運行的整個過程。代理
注意:Action運行毫不僅僅只是運行Action的execute方法這麼簡單,還包括其餘部分,完整的調用過程由ActionInvocation對象負責。xml
- 回憶一下,strutsDeepen中Action的execute方法運行的時候,是否是它的屬性就已經有了請求中的參數呢?這說明,在execute方法以前,有人偷偷的幫咱們作了這件事,把請求中的參數賦值到了Action的屬性上,這個「有人」就是剛剛說的攔截器。攔截器的運行被分紅兩部分,一部分在Action以前運行,一部分在Result以後運行,並且順序是恰好反過來的。也就是在Action執行前的順序,好比是攔截器一、攔截器二、攔截器3,那麼運行Result以後,再次運行攔截器的時候,順序就變成攔截器三、攔截器二、攔截器1了。
總之ActionInvocation對象執行的時候比較複雜,會作不少事:
- 首先,按照攔截器的引用順序依次執行各個攔截器的前置部分;
- 而後,執行Action的execute方法;
- 而後,根據execute方法返回的結果,也就是Result,在struts.xml中匹配選擇下一個頁面;
- 找到頁面後,因爲如今的頁面通常都是模板頁面,在頁面上,能夠經過Struts2自帶的標籤庫來訪問須要的數據,並生成最終頁面;
- 最後,ActionInvocation對象再按照攔截器的引用順序的倒序依次執行各個攔截器的後置部分。
- ActionInvocation對象執行完畢後,實際上就已經獲得響應對象了,也就是HttpServletResponse對象,最後按與過濾器器配置定義相反的順序依次通過過濾器,向用戶展現出響應的結果。
參考資料:http://www.iteye.com/topic/1124526