1.Interceptor介紹
攔截器(Intercepter):攔截器是struts2的核心,struts2的眾多功能都是通過攔截器來實現(xiàn)的,與Filter非常類似,不管是概念還是里面的方法
要想實現(xiàn)struts2的攔截器,那么就要實現(xiàn)Interceptor接口
對于攔截器而言,分為兩個階段:
- 定義階段
- 使用階段
一定要先定義才能使用
攔截器的實現(xiàn)步驟:
- 編寫實現(xiàn)interceptor接口的類
- 在struts.xml中的package元素下定義攔截器
- 在struts.xml的action元素下使用攔截器
雖然攔截器與Filter的配置方式不一樣,但是原理是一樣的
如果配置了攔截器,那么在服務(wù)器啟動的時候就會實例化它并調(diào)用對應(yīng)的init方法,這一點也與Filter一樣
有一點不同的是Filter可以過濾所有內(nèi)容,而攔截器只能攔截Action
整個struts2框架是靠攔截器串聯(lián)起來的
struts2提供了攔截器棧的概念,用來將攔截器按需進行歸類,方便引用,看起來使用了組合模式,因為一個interceptor-stack可以包含多個interceptor-ref也可以包含多個interceptor-stack
defaultStack攔截器棧中包含了struts2所必須用到的一些攔截器類
strust2還提供了默認攔截器機制,即如果沒有在struts.xml的Action元素下顯式的使用攔截器,那么該Action默認使用了defaultStack攔截器棧,否則的話需要顯式的引用默認攔截器棧,并通常配置在所有攔截器之后【注:經(jīng)本人測試存在defaultStack不放在所有攔截器之后的情況】
對于struts.xml而言分為三部分:
- bean
- result-type
- interceptor
攔截器本身是xwork提供的,按照之前的規(guī)律,struts2會對它進行一些封裝,成為自己的,類似StrutsTypeConverter
攔截器示例:
前端頁面:

LoginAction配置:

攔截器代碼編寫:

struts.xml配置:

結(jié)果頁面:

測試:
在前端頁面輸入hello、world并進行提交,如下圖所示:

提交后的結(jié)果如下:

控制臺輸出信息如下:

和Filter的doFilter很相似吧
此外攔截器也支持初始化參數(shù)配置,如下圖所示:

然后在對應(yīng)的攔截器中設(shè)置成員變量并提供set方法即可,這一點與Filter配置初始化參數(shù)有點不同,這里為了測試init與set方法的先后執(zhí)行順序在涉及到的方法中增加了打印語句,如下圖所示:

服務(wù)器啟動后控制臺的輸出信息如下:

可以看出set方法優(yōu)于init方法先執(zhí)行,這也是符合邏輯的,因為init方法中可能要用到對象參數(shù)
2. AbstractInterceptor介紹
因為Interceptor接口需要實現(xiàn)init、interceptor、destroy三個方法,而通常對于開發(fā)者而言只需要用到interceptor方法就行了,但是因為是接口所以必須去實現(xiàn)另外兩個方法,這樣就給開發(fā)者增加了麻煩,所以產(chǎn)生了AbstractInterceptor,類似于swing中的監(jiān)聽器適配器
它是一個抽象類,實現(xiàn)了Interceptor接口,并且空實現(xiàn)了init、destroy,所以我們在使用的時候只需要繼承它就可以了,這樣我們編寫的攔截器就更加簡潔了
3. 攔截器鏈配置演示
首先定義兩個攔截器分別為:MyInterceptor、MyAbstractInterceptor:


然后配置struts.xml文件:

使用之前的登錄頁面進行測試,控制臺輸出結(jié)果如圖所示:

從這里可以看出攔截器鏈和FilterChain的執(zhí)行流程一樣,所以之前對Filter掌握好的話,這里就很快能夠理解了
另外在這里簡單的介紹下攔截器方法所攜帶的參數(shù)ActionInvocation,通過它我們可以獲得被該攔截器所攔截的Action的對象,以及我們可以為ActionInvocation安裝PreResultListener類型的監(jiān)聽器,這個之后會
詳細介紹
4. MethodFilterInterceptor介紹
MethodFilterInterceptor(方法過濾攔截器) 它繼承了AbstractInterceptor,并且提供了一個抽象方法doInterceptor來要求我們實現(xiàn),通過在struts.xml中配置該類的excludeMethods、includeMethods屬性可以來決定到底對哪個方法進行攔截,這里要注意一點,(這里的攔截指攔截器中要執(zhí)行一些邏輯,不攔截指直接放行,不執(zhí)行攔截器中的邏輯,流程直接進入到Action)攔截器只要配置對了,那么該攔截器就會執(zhí)行,至于執(zhí)行效果就由攔截器來控制了
當一個方法名字既可以在includeMethods里獲得,又可以從excludeMethods里獲得,那么MethodFilterInterceptor認為該方法是要被攔截的即includeMethods優(yōu)先級大于excludeMethods
當在Action中引用了MethodFilterInterceptor但沒配置其子元素param時,例如下圖所示:

那么MethodFilterInterceptor攔截器會當inlcude來執(zhí)行
5. PreResultListener介紹
可以對攔截器中的actionInvocation參數(shù)安裝監(jiān)聽器,該監(jiān)聽器的執(zhí)行時機是:action執(zhí)行完之后,在渲染之前
如果在這個時機想要進行操作的話那么可以使用該監(jiān)聽器,下圖是安裝監(jiān)聽器的代碼:

當被攔截的Action執(zhí)行完之后,就會執(zhí)行該監(jiān)聽器的beforeReuslt方法,然后再執(zhí)行攔截器上的后續(xù)代碼
6. 攔截器實戰(zhàn)
需求:用攔截器實現(xiàn)全系統(tǒng)登錄驗證功能
實現(xiàn):
登錄頁面代碼:

添加新聞頁面代碼:

登錄顯示結(jié)果代碼:

新聞顯示結(jié)果代碼:

LoginAction代碼:

AddNewsAction代碼:

登錄攔截器代碼:

配置文件代碼:

7. struts.xml一拆多介紹
struts.xml一拆多其實也是為了分門別類而已,防止一個xml中內(nèi)容太過龐大,在主struts.xml中通過如下語句即可引入從struts.xml 文件:
