天天看點

Struts2 源碼分析——調結者(Dispatcher)之執行action

章節簡言

上一章筆者寫關于Dispatcher類如何處理接受來的request請求。當然讀者們也知道他并非正真的執行action操作。他隻是在執行action操作之前的準備工作。那麼誰才是正真的執行action呢?本章筆者就帶大家來看看StrutsExecuteFilter類的工作。在了解StrutsExecuteFilter類的工作之前,筆者還是希望大家回顧一下前一章講到的request請求工作。為什麼這樣子講呢?可以說StrutsExecuteFilter類的工作是建立在StrutsPrepareFilter類基礎上運作的。先相信這一點筆者不需要聲明了。筆者為了更好的了解小小的做一個張圖檔。如下

Struts2 源碼分析——調結者(Dispatcher)之執行action

從上面的圖檔我們就是很清楚StrutsPrepareFilter類做了哪些工作。而圖上的上五點對于後面的StrutsExecuteFilter類來講是非常重要的。雖然我在前面幾章也提過StrutsExecuteFilter類的知識。《Struts2 源碼分析——過濾器(Filter)》章節裡面也講過。隻是很簡單的略講一下。并沒有對他進特别的講。主要是筆者認為不了解StrutsPrepareFilter類的工作的情況下,去了解StrutsExecuteFilter類的話。是一件比較吃力的事情。好了。筆者就不多說了。讓我們進入本章的内容吧。

調結者的執行action

StrutsExecuteFilter類的工作就是執行對應的action請求。StrutsExecuteFilter類的工作還需要有一個叫ExecuteOperations類的幫助。如果看過源碼的朋友都知道,StrutsExecuteFilter類的代碼裡用了ExecuteOperations類的倆個方法。一個是:executeStaticResourceRequest方法。一個是:executeAction方法。光從字名面上我就知道他們的功能。executeStaticResourceRequest是執行靜态資源請求。如JS檔案,css檔案等。而executeAction就是執行action請求。即是筆者想要講的重點。好了。還是讓我們先看一下StrutsExecuteFilter類代碼吧。如下部分代碼

StrutsExecuteFilter類:

根據上面的紅色的代碼,讓筆者講一下總共做了幾件事件。

1.判斷目前的request請求是不是被排在外。如果就跳過去。(筆者不想過講,太簡單了)

2.判斷是否存在ExecuteOperations類的執行個體。如果沒有就初始化。相關的代碼如下。

看了代碼我們就知道StrutsExecuteFilter類的lazyInit方法做了什麼。

1).找到對應的Dispatcher執行個體。那麼Dispatcher執行個體在哪裡初始化呢?這就是StrutsPrepareFilter類的裡面。(如果不了解的讀者,請轉至Struts2 源碼分析——調結者(Dispatcher)之action請求的章節)

2).初始化StaticContentLoader類。即是用于加載JS,CSS檔案等類似的加載類。

3).初始化相關對應的PrepareOperations類和ExecuteOperations類。為了下面執行action請求準備。其中ExecuteOperations類很重要。用于執行action和加載JS,CSS檔案類似的調動者。

3.找到對應的action映射(ActionMapping類)。可以說沒有action映射就沒有辦法執行相關的action操作。讓我們看一下findActionMapping方法的代碼吧。

PrepareOperations類:

先從request請求中找到以STRUTS_ACTION_MAPPING_KEY常量為Key的ActionMapping值。如果不存在,則通過Container容器中找到的ActionMapper執行個體,并通過ActionMapper執行個體找到對應的Action映射,并存于request請求。其Key值為STRUTS_ACTION_MAPPING_KEY常量。相信讀者又看Dispatcher類的執行個體了。又跟他有關系。關于這一步其實在StrutsPrepareFilter類工作的時候就已經做過一次了。(在這裡用到ActionMapper類。關于他的作用讀者目前隻要知道所有的struts.xml上的配置action資訊都在裡面。筆者後面說找一個章節講他)

4.如果沒有找到對應的action映射(ActionMapping類)或action跳越的數量>1就是執行加載JS,CSS檔案的加載類。否則就是執行action。實話實說筆者真不知道recursionCounter > 1是什麼個意思。我隻能把他了解為跳轉的action數。筆者也做了相關通的實驗就是希望看出一些事端。可惜失敗了。

先看一下executeStaticResourceRequest方法吧。對于executeStaticResourceRequest方法。筆者在上面就講到了。他是用于加載相關的靜态資源。如CSS檔案,JS檔案。這些檔案是在JAR裡面的。我們有時候struts2相關的UI的TAG的時候,就要加載對應的CSS檔案,和JS檔案吧。這個時候他就啟作用了。讓我們看一下代碼吧。

ExecuteOperations類:

因為這部分不是筆者這系列要講的重點。如果有興趣的讀者可以自行繼續研發下去。我們可以看又是跟Dispatcher類的執行個體有關系。相信讀者這個時候很能明白筆者為什麼說Dispatcher類很重要。很能做很多事情。

關于執行action的部分就在executeAction方法裡面。讓我們看一下代碼吧。

好吧。我有一種打人的沖動。Dispatcher類的執行個體又出現。執行request請求的action也是Dispatcher類的執行個體來完成的。既然如此讓我們看一下代碼吧。如下

 從上面的代碼就能看出在執行action的内部還需要用到一個叫ActionProxy類。關于這部分知識,筆者其實這裡不想講的很細。主要這部分的知識太多了。但這裡筆者還是希望為後面的章節做好準備。ActionProxy類可以了解他是一個代理。他的主要目地就是根據action映射得到的資訊,尋找對應action類執行個體,然後執行對應的方法。其中包括加載對應的攔截器,初始化相應的結果。而這段代碼中,在ActionProxy類的execute()方法的時候,還作了相應的判斷。即是是否直接回返結果。其次還有在講到一個關于值棧的知識。這裡在獲得ActionProxy類執行個體的時候,需要得到對應值棧的資訊。但是不管如何,最後一定會把request請求的值棧重新更新一下。ValueStack(值棧)的作用相信大家都懂。我就不做過多的講解了。

本章總結

可以說相關Dispatcher類的知識點,到本章節算是結束了。筆者把Dispatcher類的功能分為三點:一是加載struts2運作的必要條件資訊;二是初始化action請求需要的資訊;三是執行request請求對應的action。而關于核心機制圖檔的橙色部分的工作大部分筆者都有展現出來。而後面的章節都是為了這三個功能點進行的。是以希望讀者能了解這三個功能。

繼續閱讀