1.Interceptor介紹
攔截器(Intercepter):攔截器是struts2的核心少辣,struts2的眾多功能都是通過攔截器來實(shí)現(xiàn)的瓤狐,與Filter非常類似,不管是概念還是里面的方法
要想實(shí)現(xiàn)struts2的攔截器辐棒,那么就要實(shí)現(xiàn)Interceptor接口
對(duì)于攔截器而言寡夹,分為兩個(gè)階段:
- 定義階段
- 使用階段
一定要先定義才能使用
攔截器的實(shí)現(xiàn)步驟:
- 編寫實(shí)現(xiàn)interceptor接口的類
- 在struts.xml中的package元素下定義攔截器
- 在struts.xml的action元素下使用攔截器
雖然攔截器與Filter的配置方式不一樣,但是原理是一樣的
如果配置了攔截器如贷,那么在服務(wù)器啟動(dòng)的時(shí)候就會(huì)實(shí)例化它并調(diào)用對(duì)應(yīng)的init方法陷虎,這一點(diǎn)也與Filter一樣
有一點(diǎn)不同的是Filter可以過濾所有內(nèi)容,而攔截器只能攔截Action
整個(gè)struts2框架是靠攔截器串聯(lián)起來的
struts2提供了攔截器棧的概念杠袱,用來將攔截器按需進(jìn)行歸類尚猿,方便引用,看起來使用了組合模式楣富,因?yàn)橐粋€(gè)interceptor-stack可以包含多個(gè)interceptor-ref也可以包含多個(gè)interceptor-stack
defaultStack攔截器棧中包含了struts2所必須用到的一些攔截器類
strust2還提供了默認(rèn)攔截器機(jī)制凿掂,即如果沒有在struts.xml的Action元素下顯式的使用攔截器,那么該Action默認(rèn)使用了defaultStack攔截器棧纹蝴,否則的話需要顯式的引用默認(rèn)攔截器棧庄萎,并通常配置在所有攔截器之后【注:經(jīng)本人測(cè)試存在defaultStack不放在所有攔截器之后的情況】
對(duì)于struts.xml而言分為三部分:
- bean
- result-type
- interceptor
攔截器本身是xwork提供的,按照之前的規(guī)律塘安,struts2會(huì)對(duì)它進(jìn)行一些封裝糠涛,成為自己的,類似StrutsTypeConverter
攔截器示例:
前端頁(yè)面:
LoginAction配置:
攔截器代碼編寫:
struts.xml配置:
結(jié)果頁(yè)面:
測(cè)試:
在前端頁(yè)面輸入hello兼犯、world并進(jìn)行提交脱羡,如下圖所示:
提交后的結(jié)果如下:
控制臺(tái)輸出信息如下:
和Filter的doFilter很相似吧
此外攔截器也支持初始化參數(shù)配置,如下圖所示:
然后在對(duì)應(yīng)的攔截器中設(shè)置成員變量并提供set方法即可免都,這一點(diǎn)與Filter配置初始化參數(shù)有點(diǎn)不同锉罐,這里為了測(cè)試init與set方法的先后執(zhí)行順序在涉及到的方法中增加了打印語句,如下圖所示:
服務(wù)器啟動(dòng)后控制臺(tái)的輸出信息如下:
可以看出set方法優(yōu)于init方法先執(zhí)行绕娘,這也是符合邏輯的脓规,因?yàn)閕nit方法中可能要用到對(duì)象參數(shù)
2. AbstractInterceptor介紹
因?yàn)镮nterceptor接口需要實(shí)現(xiàn)init、interceptor险领、destroy三個(gè)方法侨舆,而通常對(duì)于開發(fā)者而言只需要用到interceptor方法就行了,但是因?yàn)槭墙涌谒员仨毴?shí)現(xiàn)另外兩個(gè)方法绢陌,這樣就給開發(fā)者增加了麻煩挨下,所以產(chǎn)生了AbstractInterceptor,類似于swing中的監(jiān)聽器適配器
它是一個(gè)抽象類脐湾,實(shí)現(xiàn)了Interceptor接口臭笆,并且空實(shí)現(xiàn)了init、destroy,所以我們?cè)谑褂玫臅r(shí)候只需要繼承它就可以了愁铺,這樣我們編寫的攔截器就更加簡(jiǎn)潔了
3. 攔截器鏈配置演示
首先定義兩個(gè)攔截器分別為:MyInterceptor鹰霍、MyAbstractInterceptor:
然后配置struts.xml文件:
使用之前的登錄頁(yè)面進(jìn)行測(cè)試,控制臺(tái)輸出結(jié)果如圖所示:
從這里可以看出攔截器鏈和FilterChain的執(zhí)行流程一樣茵乱,所以之前對(duì)Filter掌握好的話茂洒,這里就很快能夠理解了
另外在這里簡(jiǎn)單的介紹下攔截器方法所攜帶的參數(shù)ActionInvocation,通過它我們可以獲得被該攔截器所攔截的Action的對(duì)象瓶竭,以及我們可以為ActionInvocation安裝PreResultListener類型的監(jiān)聽器督勺,這個(gè)之后會(huì)
詳細(xì)介紹
4. MethodFilterInterceptor介紹
MethodFilterInterceptor(方法過濾攔截器) 它繼承了AbstractInterceptor,并且提供了一個(gè)抽象方法doInterceptor來要求我們實(shí)現(xiàn)斤贰,通過在struts.xml中配置該類的excludeMethods玷氏、includeMethods屬性可以來決定到底對(duì)哪個(gè)方法進(jìn)行攔截,這里要注意一點(diǎn)腋舌,(這里的攔截指攔截器中要執(zhí)行一些邏輯盏触,不攔截指直接放行,不執(zhí)行攔截器中的邏輯块饺,流程直接進(jìn)入到Action)攔截器只要配置對(duì)了赞辩,那么該攔截器就會(huì)執(zhí)行,至于執(zhí)行效果就由攔截器來控制了
當(dāng)一個(gè)方法名字既可以在includeMethods里獲得授艰,又可以從excludeMethods里獲得辨嗽,那么MethodFilterInterceptor認(rèn)為該方法是要被攔截的即includeMethods優(yōu)先級(jí)大于excludeMethods
當(dāng)在Action中引用了MethodFilterInterceptor但沒配置其子元素param時(shí),例如下圖所示:
那么MethodFilterInterceptor攔截器會(huì)當(dāng)inlcude來執(zhí)行
5. PreResultListener介紹
可以對(duì)攔截器中的actionInvocation參數(shù)安裝監(jiān)聽器,該監(jiān)聽器的執(zhí)行時(shí)機(jī)是:action執(zhí)行完之后,在渲染之前
如果在這個(gè)時(shí)機(jī)想要進(jìn)行操作的話那么可以使用該監(jiān)聽器旅赢,下圖是安裝監(jiān)聽器的代碼:
當(dāng)被攔截的Action執(zhí)行完之后,就會(huì)執(zhí)行該監(jiān)聽器的beforeReuslt方法洲押,然后再執(zhí)行攔截器上的后續(xù)代碼
6. 攔截器實(shí)戰(zhàn)
需求:用攔截器實(shí)現(xiàn)全系統(tǒng)登錄驗(yàn)證功能
實(shí)現(xiàn):
登錄頁(yè)面代碼:
添加新聞頁(yè)面代碼:
登錄顯示結(jié)果代碼:
新聞顯示結(jié)果代碼:
LoginAction代碼:
AddNewsAction代碼:
登錄攔截器代碼:
配置文件代碼:
7. struts.xml一拆多介紹
struts.xml一拆多其實(shí)也是為了分門別類而已,防止一個(gè)xml中內(nèi)容太過龐大圆凰,在主struts.xml中通過如下語句即可引入從struts.xml 文件: