天天看點

Struts2 源碼分析——過濾器(Filter)

章節簡言

上一章筆者試着建一個Hello world的例子。是一個空白的struts2例子。明白了運作struts2至少需要用到哪一些Jar包。而這一章筆者将根據前面章節(Struts2 源碼分析——核心機制)裡的機制圖檔來分析源碼。如果還不明白核心機制的朋友,請轉到對應的章節進行閱讀。筆者為了友善讀者閱讀,也把圖檔在次貼到了本章中。如下

Struts2 源碼分析——過濾器(Filter)

根據圖檔筆者就明白我們首要分析便是橙黃色(Servlet Filters)。也就是傳說的過濾器(Filter)。相信看過筆者前面幾個章節的讀者都明白struts2的配置方式有二種。即是StrutsPrepareFilter+StrutsExecuteFilter和StrutsPrepareAndExecuteFilter。不管是哪一種大部分都是一樣子。筆者用的是StrutsPrepareFilter+StrutsExecuteFilter來分析。那麼讓我們看看關于他們到底做了些什麼。Prepare意為“準備”。猜的沒有錯。StrutsPrepareFilter類就是為了開啟struts2之前加載一個相關的配置和執行的必要資訊。同理,Execute意為“運作”。我們也就可以想像StrutsExecuteFilter類就是執行struts2。所謂分析就是要有一種敢于想像和猜測的心态。然後在證明就行了。

另外這裡有聲明一下:筆者這裡隻想講一些有關struts2相關的知識。而像SiteMesh之類的筆者并不會深入。

StrutsPrepareFilter類的工作

StrutsPrepareFilter這個類必須在StrutsExecuteFilter類之前運作。否則就會出錯。當然struts2運作起來的時候,架構也有相關的提示你。那麼先讓我們看一下代碼吧。如下

Struts2 源碼分析——過濾器(Filter)
Struts2 源碼分析——過濾器(Filter)

StrutsPrepareFilter 類的源碼

上面的源碼也做了一些簡單的注解。當然這是筆者的了解。如果你看了源碼覺得筆者了解的不對。沒事!隻要讀者自己心裡面明白原理的話就可以了。我們可以看到了好多的類,對于筆者來講以前有過經驗,看起來比較輕松。但是對于四年前初學者的我來講,那真是天書。筆者一個一個解釋給讀者聽也不現實。這裡筆者隻把主要的相關類拿出來講解。希望讀者們見諒!StrutsPrepareFilter類現實于接口StrutsStatics。這接口都是大量常量。而StrutsPrepareFilter類本身有二個成員變量。其中一個成員變量prepare(PrepareOperations類)的工作如下。

prepare成員變量的工作:

1.設定request請求的本地化。即是:本地語言和編碼格式。

2.建立一個新的action上下文。對于上下文不了解的讀者可以檢視相關的文章。如果不行的話,筆者認為你可以了解為進入房間的門一樣子。action請求則是房間。建立一個房間就有一個新的門。新action請求就有一個新的action上下文。

3.把目前的Dispatcher執行個體存放到目前的本地線程(ThreadLocal)中。而Dispatcher類是一個重要的核心類,struts2的action請求就是靠他來執行的。(對于Dispatcher類的作用不了解的話。沒有事。後面我會對Dispatcher進行講解)

4.把HttpServletRequest請求封裝成為StrutsRequestWrapper或是MultiPartRequestWrapper。可以說這部分的工作也是靠Dispatcher執行個體來執行的。

5.找到action映射類(ActionMapping)的執行個體。并把他存在到request請求裡面。他對應的Key為“struts.actionMapping”; 讀者會問ActionMapping類是什麼東東。現在可以了解為裡面存放使用者action的配置資訊。大白話就是使用者在位址欄上輸入URL找到對應的action類。

以上是prepare成員變量的工作,他是主要目的就是根據request請求找到對應action映射。以便于StrutsExecuteFilter類根據action映射類裡面的資訊找到對應的使用者action類,并執行。從這裡筆者就可以明顯感覺出來,StrutsPrepareFilter類是執行action請求之前的相關準備工作。那麼敏感的讀者就會問:“正常在這之前應該會加載或初始化相關的配置資訊才對啊?不然他後面執行action請求什麼工作呢?”。沒有錯。讓我們看一下過濾器(Filter)的方法init吧。可以明确的指出加載相關的配置資訊就在這裡進行的。他的工作如下

init方法:

1.檢視使用者是否有自定義日志類。如果有,初始化并執行個體使用者定義的日志類。存放到LoggerFactory類裡面。LoggerFactory類裡面用的是單例模式。

2.執行個體化Dispatcher類,并初始化加載相關的配置的資訊檔案。如 default.properties檔案,struts-default.xml檔案等等。

3.執行個體化PrepareOperations類,Dispatcher執行個體存放進去。為之後的request請求工作做準備。即是上面PrepareOperations類所講的。

4.加載使用者自定義不應該被外部通路的action相對應的正規表達式。這邊也就是StrutsPrepareFilter類裡面的另一個成員變量。

正如上述所講的就是StrutsPrepareFilter類的工作。簡單點講就是為action請求執行之前做好一切準備的類。其中init方法就是用于加載相關配置檔案,初始化資訊的工作。而PrepareOperations類是用于request請求的處理。其中包設定格式,找對應的action映射類等等操作。即是ActionMapping類。

StrutsExecuteFilter類的工作

上面講到StrutsPrepareFilter類的工作,那麼對于StrutsExecuteFilter類的工作就顯得很簡單。就是執行action請求。讓我們先看一下代碼吧。如下

Struts2 源碼分析——過濾器(Filter)
Struts2 源碼分析——過濾器(Filter)

StrutsExecuteFilter類的源碼

筆者在這個類上的注解比較簡單,主要是筆者不知道這個類什麼樣子去講。因為這個類比StrutsPrepareFilter類來講簡單多了。工作也很單一。是以筆者一下子不知道要什麼樣子去注解。筆者認為這個類的重點有二個地方。一是lazyInit方法,二是ExecuteOperations類的工作。而其中lazyInit方法主要是用于初始化相關需要的類。并沒有值得注意的點。那麼為什麼筆者卻要說他是重點之一呢?問題在于他還有一個工作是初始化靜态内容加載器(StaticContentLoader類)。可惜不是本章的重點。是以筆者要講的是ExecuteOperations類的工作。如下

ExecuteOperations類的工作:

1.組裝相關的Map類。如requestMap,params,session 等。

2.找到ActionProxy類。該類是用于執行action請求的。也是關鍵的類。(後面章節會講到)

3.組裝action請求執行的結果。也是關鍵的類。(後面章節會講到)

StrutsExecuteFilter類的工作目前隻需要知道他是執行action請求的。如果讀者不明白不要擔心。筆者後面會講到。

本章總結

本章的重點并不是要知道如何去執行action請求。而是知道在執行action請求之前要做些什麼工作。隻要明白了這一點我們就知道目标是什麼。是以在本章筆者在講StrutsPrepareFilter類的時候,講的比較多。就是要讓讀者明白準備工作都有哪些什麼。

繼續閱讀