這篇文章大部分是轉(zhuǎn)載的,雖然不知道作者是誰,但是還是非常膜拜的,描述的非常清晰,我覺得要是自己去陳訴也沒有這么好,中間我修改了最新的核心控制器名稱,主要是struts2的核心控制器現(xiàn)在并不是FilterDispatcher對(duì)象,而是StrutsPRepareAndExcuteFilter對(duì)象;中間有許多圖片還是FilterDisptcher,我這邊偷下懶,大家知道就行
第一步 :我們先來看下struts2官方提供的運(yùn)行流程圖
 
這張圖上分了好多塊,彼此之間相互聯(lián)系,先瀏覽一下各塊的名字,再留心一下運(yùn)行圖最下面的圖例,分為四種顏色。
第二部分我們粗略的陳訴下各個(gè)模塊作用
第三部分接下來我們來真正陳訴下運(yùn)行流程
前提:我們正在模擬用戶登入,進(jìn)入index.jsp頁面,該頁面有兩個(gè)輸入框,分別是賬號(hào)與密碼,還有提交按鈕,當(dāng)輸入的信息后然后提交到后臺(tái)處理,插入web.xml文件中的過濾器配置
過程:
1:首先是在登錄頁面,用戶填入帳號(hào)和密碼,然后點(diǎn)擊提交按鈕,好了,就從這里開始分析背后的處理流程,這是我們進(jìn)行分析的起點(diǎn)。
2:當(dāng)用戶提交登錄請(qǐng)求后,請(qǐng)求的URL為:“/helloworld /helloworldAction.action”,請(qǐng)求會(huì)被Tomcat服務(wù)器接收到,Tomcat服務(wù)器會(huì)根據(jù)請(qǐng)求URL中的web上下文,也就是 “/helloworld”,來選擇處理這個(gè)請(qǐng)求的Web應(yīng)用,那就是由helloworld這個(gè)web工程來處理這個(gè)請(qǐng)求。
3:Web容器會(huì)去讀取helloworld這個(gè)工程的web.xml,在web.xml中進(jìn)行匹配,發(fā)現(xiàn)后綴為“.action”的請(qǐng)求,由struts2這個(gè)過濾器來進(jìn)行處理,根據(jù)Filter的配置,找到實(shí)際的類為FilterDispatcher。
4:Web容器會(huì)獲取FilterDispatcher這個(gè)類的實(shí)例,然后回調(diào)doFilter方法,進(jìn)行真正的處理。StrutsPrepareAndExcuteFilter作為前端控制器,是整個(gè)Struts2的調(diào)度中心。
注意:在架構(gòu)圖上,可以看到有三個(gè)過濾器層次,分別是ActionContextCleanUp、 SiteMesh等其他過濾器和FilterDispatcher。這三個(gè)層次中,ActionContextCleanUp和 FilterDispatcher是Struts2的過濾器,而SiteMeshSiteMesh等其他過濾器不是。
StrutsPrepareAndExcuteFilter是任何一個(gè)Struts2應(yīng)用都需要配置的,一般出現(xiàn)在過濾器鏈的最后;如果在StrutsPrepareAndExcuteFilter前出現(xiàn)了如SiteMesh這種特殊的過濾器,還必須在SiteMesh前引用Struts2的ActionContextCleanUp過濾器。
在前面的helloworld中,并沒有出現(xiàn)SiteMesh這種特殊的過濾器,所以只需要引用StrutsPrepareAndExcuteFilter就可以了。
這就相當(dāng)于前進(jìn)到Struts2架構(gòu)圖上的第一步,如下所示:

 
5:StrutsPrepareAndExcuteFilter將請(qǐng)求轉(zhuǎn)發(fā)給ActionMapper。ActionMapper負(fù)責(zé)識(shí)別當(dāng)前的請(qǐng)求是否需要Struts2做出處理。這就相當(dāng)于前進(jìn)到Struts2架構(gòu)圖上的第二步,如下所示:

 
6:ActionMapper告訴StrutsPrepareAndExcuteFilter,需要處理這個(gè)請(qǐng)求,StrutsPrepareAndExcuteFilter會(huì)停止過濾器鏈以后的部分,所以通常情況下:StrutsPrepareAndExcuteFilter應(yīng)該出現(xiàn)在過濾器鏈的最后。然后建立一個(gè)ActionProxy對(duì)象,這個(gè)對(duì)象作為Action與xwork之間的中間層,會(huì)代理Action的運(yùn)行過程。
這就相當(dāng)于前進(jìn)到Struts2架構(gòu)圖上的第三步,如下所示:
                   
 
7:ActionProxy對(duì)象剛被創(chuàng)建出來的時(shí)候,并不知道要運(yùn)行哪個(gè)Action,它手里只有從StrutsPrepareAndExcuteFilter中拿到的請(qǐng)求的URL。這時(shí)候,它去向ConfigurationManager詢問到底要運(yùn)行哪個(gè)Action。
回憶一下,某個(gè)特定的URL由哪個(gè)Action響應(yīng)由誰負(fù)責(zé),定義在什么地方呢?沒錯(cuò),在struts.xml里面。而 ConfigurationManager就是負(fù)責(zé)讀取并管理struts.xml的,可以簡單的理解為ConfigurationManager是 struts.xml在內(nèi)存中的映像。
在服務(wù)器啟動(dòng)的時(shí)候,ConfigurationManager會(huì)一次性的把struts.xml中的所有信息讀到內(nèi)存里,并緩存起來,以保證ActionProxy拿著來訪的URL向他詢問要運(yùn)行哪個(gè)Action的時(shí)候,就可以直接匹配、查找并回答了。
這就相當(dāng)于前進(jìn)到Struts2架構(gòu)圖上的第四步和第五步了,如下所示:

 
8:ActionProxy拿到了運(yùn)行哪個(gè)Action、相關(guān)的攔截器以及所有可能使用的result信息,就可以著手建立ActionInvocation對(duì)象了,ActionInvocation對(duì)象描述了Action運(yùn)行的整個(gè)過程。
注意:Action運(yùn)行絕不僅僅只是運(yùn)行Action的execute方法這么簡單,還包括其他部分,完整的調(diào)用過程由ActionInvocation對(duì)象負(fù)責(zé)。
這就相當(dāng)于前進(jìn)到Struts2架構(gòu)圖上的第六步,如下所示:

 
9:回憶一下,HelloWorld中Action的execute方法運(yùn)行的時(shí)候,是不是它的屬性就已經(jīng)有了請(qǐng)求中的參數(shù)呢?這說明,在execute方法之前,有人偷偷的幫我們做了這件事,把請(qǐng)求中的參數(shù)賦值到了Action的屬性上,這個(gè)“有人”就是剛剛說的攔截器。
攔截器的運(yùn)行被分成兩部分,一部分在Action之前運(yùn)行,一部分在Result之后運(yùn)行,而且順序是剛好反過來的。也就是在Action執(zhí)行前的順序,比如是攔截器1、攔截器2、攔截器3,那么運(yùn)行Result之后,再次運(yùn)行攔截器的時(shí)候,順序就變成攔截器3、攔截器2、攔截器1了。
總之ActionInvocation對(duì)象執(zhí)行的時(shí)候比較復(fù)雜,會(huì)做很多事:
這就相當(dāng)于前進(jìn)到Struts2架構(gòu)圖上的第七步,如下所示:

 
這就相當(dāng)于前進(jìn)到Struts2架構(gòu)圖上的第八步,如下所示:

 然后根據(jù)execute方法返回的結(jié)果,也就是Result,在struts.xml中匹配選擇下一個(gè)頁面,這就相當(dāng)于前進(jìn)到Struts2架構(gòu)圖上的第九步,如下所示:

 
這就相當(dāng)于前進(jìn)到Struts2架構(gòu)圖上的第十步,如下所示:

 
這就相當(dāng)于前進(jìn)到Struts2架構(gòu)圖上的第十一步,如下所示:

 
10:ActionInvocation對(duì)象執(zhí)行完畢后,實(shí)際上就已經(jīng)得到響應(yīng)對(duì)象了,也就是HttpServletResponse對(duì)象,最后按與過濾器器配置定義相反的順序依次經(jīng)過過濾器,向用戶展示出響應(yīng)的結(jié)果。
這就相當(dāng)于前進(jìn)到Struts2架構(gòu)圖上的第十二步,得到最終完整的系統(tǒng)架構(gòu)圖了

新聞熱點(diǎn)
疑難解答
圖片精選
網(wǎng)友關(guān)注