第一節(jié):Struts2的攔截器
1.1 攔截器的概述:
攔截器,在AOP(Aspect - Oriented Programming)中用于在某個(gè)方法或字段被訪問(wèn)之前谆扎,進(jìn)行攔截然后在之前或之后加入某些操作策泣。攔截是AOP的一種實(shí)現(xiàn)策略症虑。
在WebWork的中文文檔的解釋為——攔截器是動(dòng)態(tài)攔截Action調(diào)用的對(duì)象连霉。它提供了一些機(jī)制可以使開(kāi)發(fā)者可以定義在一個(gè)action執(zhí)行的前后執(zhí)行的代碼,也可以在一個(gè)Action執(zhí)行前阻止其執(zhí)行佛呻。同時(shí)也是提供了一種可以提取action中可重用的部分的方式裳朋。
談到攔截器,還有一個(gè)詞——攔截器鏈(Interceptor Chain吓著,在Struts2中稱為攔截棧Interceptor Stack)鲤嫡。攔截器鏈就是將攔截器按一定的順序聯(lián)結(jié)成一條鏈。在訪問(wèn)被攔截的方法或字段時(shí)绑莺,攔截器鏈中的攔截器就會(huì)按其之前定義的順序被調(diào)用暖眼。
1.2 攔截器的實(shí)現(xiàn)原理:
攔截器方法都是通過(guò)代理的方式來(lái)調(diào)用的。當(dāng)請(qǐng)求送達(dá)Struts2的ServletDispatcher時(shí)纺裁,Struts2會(huì)查找配置文件罢荡,并根據(jù)其配置實(shí)例化相對(duì)的攔截器對(duì)象,然后串成一個(gè)列表对扶,最后一個(gè)一個(gè)地調(diào)用列表中的攔截器。
Struts2攔截器是可插拔的惭缰,攔截器是AOP的一種實(shí)現(xiàn)浪南。Struts2攔截器棧就是將攔截器按一定的順序聯(lián)結(jié)成一條鏈。在訪問(wèn)被攔截的方法或字段時(shí)漱受,Struts2攔截器鏈中的攔截器就會(huì)按其之前定義的順序被調(diào)用络凿。
1.3 攔截器的執(zhí)行流程
1.4 自定義攔截器
若需要實(shí)現(xiàn)攔截器類,就需要直接或間接的實(shí)現(xiàn)com.opensymphony.xwork2.interceptor接口昂羡,其接口定義代碼如下:
import com.opensymphony.xwork2.ActionInvocation;
import java.io.Serializable;
public interface Interceptor extends Serializable {
void destroy();
void init();
String intercept(ActionInvocation var1) throws Exception;
}
該接口提供了三個(gè)方法絮记,其具體介紹如下:
- void init():該方法在攔截器被創(chuàng)建后會(huì)立即被調(diào)用,它在攔截器的生命周期內(nèi)只被調(diào)用一次虐先,可以在該方法中對(duì)相關(guān)資源進(jìn)行必要的初始怨愤。
- void destroy():該方法與init方法相對(duì)應(yīng),在攔截器被銷毀之前蛹批,將調(diào)用該方法來(lái)釋放和攔截器相關(guān)的資源撰洗。它在攔截器的生命周期內(nèi)篮愉,也只被調(diào)用一次。
- String intercept(ActionInvocation invocation)throws Exception:該方法是攔截器的核心方法差导,用來(lái)添加真正執(zhí)行攔截工作的代碼试躏,實(shí)現(xiàn)具體的攔截操作。它返回一個(gè)字符串作為邏輯視圖设褐,系統(tǒng)根據(jù)返回的字符串跳轉(zhuǎn)到對(duì)應(yīng)的視圖資源颠蕴。每攔截一個(gè)動(dòng)作請(qǐng)求,該方法都會(huì)被調(diào)用一次助析。該方法的ActionInvocation參數(shù)包含了被攔截Action的引用犀被,可以通過(guò)該參數(shù)的invoke()方法,將控制權(quán)給下一個(gè)攔截器或者轉(zhuǎn)給Action的execute()方法貌笨。
如果需要自定義攔截器弱判,只需要實(shí)現(xiàn)Interceptor接口的三個(gè)方法即可。然而在實(shí)際的開(kāi)發(fā)中锥惋,除了實(shí)現(xiàn)Interceptor接口可以自定義攔截器外昌腰,更常用的一種方式是繼承抽象攔截器類AbstracIntercepter。該類實(shí)現(xiàn)了Interceptor接口膀跌,并且提供了init()方法和destory()方法的空實(shí)現(xiàn)遭商。使用時(shí),可以繼承該抽象類捅伤,而不用實(shí)現(xiàn)那些不必要的方法劫流。攔截器類AbstractInterceptor中定義的方法如下所示:
public abstract class AbstractInterceptor implements Interceptor {
public AbstractInterceptor() {
}
public void init() {
}
public void destroy() {
}
public abstract String intercept(ActionInvocation var1) throws Exception;
}
從上述代碼中可以看出,AbstractInterceptor類已經(jīng)實(shí)現(xiàn)了Interceptor接口的所有方法丛忆,一般情況下祠汇,只需繼承AbstractInterceptor類,實(shí)現(xiàn)interceptor()方法就可以創(chuàng)建自定義攔截器熄诡。
只有當(dāng)自定義的攔截器需要打開(kāi)系統(tǒng)資源時(shí)可很,才需要覆蓋AbstracInterceptor類的init()方法和destroy()方法。與實(shí)現(xiàn)Interceptor接口相比凰浮,繼承AbstractInterceptor類的方法更為簡(jiǎn)單我抠。
1.5 攔截器的配置
- 攔截器
要想讓攔截器起作用,首先要對(duì)它進(jìn)行配置袜茧。攔截器的配置是在struts.xml文件中完成的菜拓,它通常以<interceptor>標(biāo)簽開(kāi)頭,以</interceptor>標(biāo)簽結(jié)束笛厦。定義攔截器的語(yǔ)法格式如下:
<interceptors>
<interceptor name="interceptorDemo01" class="com.seapp.struts2.interceptor.MyInterceptor02">
<param name="paramName">paramValue</param>
</interceptor>
</interceptors>
上述語(yǔ)法格式中纳鼎,name屬性用來(lái)指定攔截器的名稱,class屬性用于指定攔截器的實(shí)現(xiàn)類裳凸。有時(shí)喷橙,在定義攔截器時(shí)需要傳入?yún)?shù)啥么,這時(shí)需要使用<param>標(biāo)簽,其中name屬性用來(lái)指定參數(shù)的名稱贰逾,paramValue表示參數(shù)的值悬荣。
- 在實(shí)際開(kāi)發(fā)中,經(jīng)常需要在Action執(zhí)行前同時(shí)執(zhí)行多個(gè)攔截動(dòng)作疙剑,如:用戶登錄檢查氯迂、登錄日志記錄以及權(quán)限檢查等。這時(shí)言缤,可以把多個(gè)攔截器組成一個(gè)攔截器棧嚼蚀。在使用時(shí),可以將棧內(nèi)多個(gè)攔截器當(dāng)成一個(gè)整體來(lái)引用管挟。當(dāng)攔截器棧被附加到一個(gè)Action上時(shí)轿曙,在執(zhí)行Action之前必須先執(zhí)行攔截器棧中的每一個(gè)攔截器。
-攔截器:
<interceptors>
<interceptor-stack name="interceptorStackName">
<interceptor-ref name="interceptorName"/>
...
</interceptor-stack>
</interceptors>
在上述的語(yǔ)法中僻孝,interceptorStackName值表示配置的攔截器的名稱导帝;interceptorName值表示攔截器的名稱。除此之外穿铆,在一個(gè)攔截器棧中還可以包含另一個(gè)攔截器棧您单,示例代碼如下:
<interceptors>
<!--聲明攔截器-->
<interceptor name="interceptor" class="com.seapp.struts2.interceptor.MyInterceptor">
</interceptor>
<interceptor name="interceptorDemo01" class="com.seapp.struts2.interceptor.MyInterceptor02">
<param name="paramName">paramValue</param>
</interceptor>
<!--定義一個(gè)攔截器棧myStack,該攔截器棧中包含兩個(gè)攔截器和一個(gè)攔截器棧-->
<interceptor-stack name="myStack">
<interceptor-ref name="defaultStack"/>
<interceptor-ref name="interceptor"/>
<interceptor-ref name="interceptorDemo01"/>
</interceptor-stack>
</interceptors>
在上述代碼中,定義的攔截器棧是myStack荞雏,在myStack棧中虐秦,除了引用了兩個(gè)自定義的攔截器interceptor和interceptorDemo01外,還引用了一個(gè)內(nèi)置攔截器棧defaultStack凤优,這個(gè)攔截器是必須要引入的悦陋。