章節簡言
上一章筆者講到關于如何加載配置檔案裡面的package元素節點資訊。相信讀者到這裡心裡面對struts2在啟動的時候加載相關的資訊有了一定的了解和認識。而本章将講到關于struts2啟動成功之後,接受到使用者action請求之後如何處理并找到對應的action類。可以說這章是講述《Struts2 源碼分析——調結者(Dispatcher)之執行action》章節之後的事情。即是核心機制圖檔的藍色(Struts core)分部的知識點。通過前面幾章節的内容至少我們知道了struts2啟動成之後,會把相關的資訊存放在Container容器和DefaultConfiguration類的執行個體裡面。而Dispatcher類的執行個體便是這倆個類的中間調節者。(不懂得的讀者請先檢視一下前面幾章節來在)
Action代理類的建立
通過《Struts2 源碼分析——調結者(Dispatcher)之執行action》章節我們知道執行action請求,最後會落到Dispatcher類的serviceAction方法上面。可惜筆者并沒有在這一章裡面對他自己詳細的講解。先讓我們看一下代碼吧?知道他在做什麼吧。如下
Dispatcher類:
1.根據傳入的參數request, response, mapping來建立一個上下文Map。上下文Map就是一個存了關于RequestMap類,SessionMap類,ApplicationMap類等執行個體。即是request請求相關的資訊,隻是把他變成了對應的MAP類而以。
2.從request請求中找到對應的值棧(ValueStack)。如果沒有就建立值棧。然後存放到上下文Map裡面,對應的KEY為ActionContext.VALUE_STACK常量的值。即是"com.opensymphony.xwork2.util.ValueStack.ValueStack"。
3.從Mapping參數中提取對應的request請求的命名空間,action名字和方法名。
4.從Container容器中找到ActionProxyFactory類,并根據request請求的命名空間,action名字和方法名,上下文Map來獲得對應的action代理類(ActionProxy)。然後更新request請求中的對應的值棧(ValueStack)。
5.根據Mapping參數來判斷是否為直接輸出結果。還是執行action代理類。
6.最後在判斷之前是否request請求沒有找到對應的值棧(ValueStack)。如果有找到值棧(ValueStack),則更新request請求中的對應的值棧(ValueStack)。
是以我們的目标很明确就是要去看一下action代理類(ActionProxy)。了解他到底做了什麼。才能明白如何找到對應的action類,并執行對應的方法。從上面我們也知道action代理類的建立是通過ActionProxyFactory接口執行個體來進行的。即是DefaultActionProxyFactory類的執行個體。顯然就是一個簡章的工廠模式。讓我們看一下建立action代理類的代碼吧。
DefaultActionProxyFactory類:
看到了吧。在建立action代理類的時候還要用到ActionInvocation接口的執行個體。即是DefaultActionInvocation類的執行個體。前面幾章筆者曾經講過Dispatcher類才是正真執行action類執行個體的人。這裡筆者不得不在提一下。Dispatcher類是重要的調結者,DefaultActionInvocation類是執行action類執行個體的行動者。而action代理類(ActionProxy類)則是他們之間的中間人。相當于Dispatcher類通過action代理類(ActionProxy類)指令DefaultActionInvocation類去執行action類執行個體。
Action代理類的準備工作
action代理類(ActionProxy類)在指令DefaultActionInvocation類去執行action類執行個體之前,還是有做了一些準備工作。好吧。新航道托福筆者還是希望通過代碼來說話。看一下代碼吧。
DefaultActionProxy類:
從上面的代碼,我們可以看出在執行action類之前,大概做了倆件準備工作:
1.獲得ActionConfig類執行個體。并通過ActionConfig類執行個體找到對應的方法名。ActionConfig類就是存放配置檔案裡面的action元素節點的資訊。
2.實初始化DefaultActionInvocation類的執行個體。即是根據ActionProxy類執行個體找到對應的action類執行個體(使用者自己定義的類)。
代碼中倆個方法是筆者希望讀者明白的。一個是DefaultActionProxy類的resolveMethod方法。一個是DefaultActionInvocation類的init方法。為什麼要講這倆個方法。上面的倆件事情主要的功能都是在這倆個方法裡面。讓我們看一代碼吧?
DefaultActionProxy類:
DefaultActionInvocation類:
看了代碼就能清楚的知道一件事情。如果我們在struts.xml配置檔案裡面action元素節點裡面沒有指定方法的時候,就用會預設的方法。即是execute方法。而關于init方法就能明确明白為了找到action類并執行個體他。init方法裡面調用了倆個非重要的方法。一個是用于建立action類執行個體的方法createAction。一個是用于獲得相關攔截器的方法createInterceptors。看一下代碼吧。
相信讀者一定能看的懂代碼吧。倆個方法中在筆者看來最重要的展現便是ObjectFactory類。ObjectFactory類是用于新一個執行個體的。上面的方法裡面就是用ObjectFactory類來建立一個action類的執行個體。
好了。到了這裡面action代理類(ActionProxy類)的準備工作算是做完了。讓筆者理一下。準備工作完成之後。筆者至少知道action類執行個體有了。要執行的方法名也有了。要執行的攔截器也有了。有了這些資訊難道strtus2會不知道去執行對應的工作嗎?
Action代理類的主要工作
action代理類(ActionProxy類)的準備工作完成之後,就開始執行了。最頂部的代碼中就很明确的看的出來(serviceAction方法)。先是根據參數mapping來判斷是否為直接回返。如果不是才去執行action代理類(ActionProxy類)的execute方法。這便是action代理類(ActionProxy類)的主要工作。即是執行action請求。那麼讓我們看一下action代理類(ActionProxy類)的execute方法源碼吧。
很好。從紅色的代碼部分我們就知道就是去執行DefaultActionInvocation類執行個體的invoke方法。DefaultActionInvocation類和action代理類(ActionProxy類)的關系看起相當的複雜。可以說是我中有你,你中有我。DefaultActionProxy類建立的時候需要DefaultActionInvocation類的執行個體。而DefaultActionInvocation類的執行個體初始化的時候,action代理類(ActionProxy類)的執行個體會傳DefaultActionInvocation類裡面并存放起來。即是在init方法的時候。值得注意的是這個時候的Action上下文(ActionContext類)有發生一件細微的變化。不是以前的了。而是從DefaultActionInvocation類的執行個體中得來的。cleanupContext參數表示要不要執行完成之後就清除掉目前的。把原來的放在去。最後回返結果。
本章總結
本章主要是講到關于action代理類(ActionProxy類)的工作。知道了DefaultActionInvocation類是用去執行action類的行動者。而Dispatcher類是調結者。action代理類(ActionProxy類)是DefaultActionInvocation類和Dispatcher類的中間人。即是Dispatcher類通過action代理類(ActionProxy類)指令DefaultActionInvocation類去執行action類執行個體。