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


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

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

StrutsPrepareFilter類的工作

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

  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請求。讓我們先看一下代碼吧。如下

  StrutsExecuteFilter類的源碼

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

ExecuteOperations類的工作:

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

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

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

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

本章總結

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


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM