Struts2攔截器的實(shí)現(xiàn)原理是什么?很多新手對(duì)此不是很清楚,為了幫助大家解決這個(gè)難題,下面小編將為大家詳細(xì)講解,有這方面需求的人可以來(lái)學(xué)習(xí)下,希望你能有所收獲。
公司主營(yíng)業(yè)務(wù):成都做網(wǎng)站、成都網(wǎng)站制作、成都外貿(mào)網(wǎng)站建設(shè)、移動(dòng)網(wǎng)站開(kāi)發(fā)等業(yè)務(wù)。幫助企業(yè)客戶(hù)真正實(shí)現(xiàn)互聯(lián)網(wǎng)宣傳,提高企業(yè)的競(jìng)爭(zhēng)能力。成都創(chuàng)新互聯(lián)公司是一支青春激揚(yáng)、勤奮敬業(yè)、活力青春激揚(yáng)、勤奮敬業(yè)、活力澎湃、和諧高效的團(tuán)隊(duì)。公司秉承以“開(kāi)放、自由、嚴(yán)謹(jǐn)、自律”為核心的企業(yè)文化,感謝他們對(duì)我們的高要求,感謝他們從不同領(lǐng)域給我們帶來(lái)的挑戰(zhàn),讓我們激情的團(tuán)隊(duì)有機(jī)會(huì)用頭腦與智慧不斷的給客戶(hù)帶來(lái)驚喜。成都創(chuàng)新互聯(lián)公司推出青山免費(fèi)做網(wǎng)站回饋大家。
Struts2的核心在于它復(fù)雜的攔截器,幾乎70%的工作都是由攔截器完成的。比如我們之前用于將上傳的文件對(duì)應(yīng)于action實(shí)例中的三個(gè)屬性的fileUpload攔截器,還有用于將表單頁(yè)面的http請(qǐng)求參數(shù)設(shè)置成action中對(duì)應(yīng)的屬性的param攔截器等??傊?,在整個(gè)Struts框架中攔截器的作用是相當(dāng)大的,本篇將從以下幾點(diǎn)詳細(xì)介紹下有關(guān)Struts攔截器的內(nèi)容:
一、攔截器在Struts中的作用
在我們的web.xml中,我們配置了一個(gè)過(guò)濾器,實(shí)現(xiàn)將所有請(qǐng)求交付StrutsPrepareAndExecuteFilter類(lèi)。一旦接受到任意action的請(qǐng)求,該類(lèi)會(huì)創(chuàng)建和初始化一個(gè)ActionProxy實(shí)例,它代理了具體的action,在其中我們可以添加任意攔截器在execute方法執(zhí)行之前和之后做一些額外的操作,最終會(huì)調(diào)用該action實(shí)例的execute方法,為用戶(hù)返回視圖結(jié)果字符串,然后系統(tǒng)會(huì)根據(jù)該視圖結(jié)果字符串調(diào)取相應(yīng)的視圖頁(yè)面。下圖是攔截器和action之間的關(guān)系:
這是一種典型的AOP思想,當(dāng)我們?cè)赟truts.xml中定義一個(gè)包的時(shí)候,大部分情況下我們會(huì)繼承struts-default文件,所以雖然我們?cè)谧约旱呐渲梦募胁](méi)有手動(dòng)配置任何的攔截器,但是我們創(chuàng)建的action卻被很多攔截器攔截處理,就是因?yàn)閟truts-default中配置的攔截器生效了。Struts中內(nèi)建了很多的攔截器,他們大多被配置在struts-default文件中,詳細(xì)的內(nèi)建攔截器的介紹可以參考官方API,接下來(lái)我們看如何自定義一個(gè)攔截器。
二、自定義攔截器實(shí)現(xiàn)類(lèi)
想要實(shí)現(xiàn)自己的攔截器類(lèi)只需要實(shí)現(xiàn) com.opensymphony.xwork2.interceptor.Interceptor.Interceptor 接口即可,該接口中有如下幾個(gè)方法:
public abstract void destroy(); public abstract void init(); public abstract String intercept(ActionInvocation paramActionInvocation) throws Exception;
init 方法在執(zhí)行攔截方法之前回調(diào),主要用于初始化一些資源,destroy 與init 方法對(duì)應(yīng),在攔截器實(shí)例被銷(xiāo)毀之前回調(diào),主要用于釋放在init 方法中打開(kāi)的資源。intercept 方法是我們的攔截方法,我們可以重寫(xiě)該方法來(lái)完成對(duì)action實(shí)例的攔截,該方法具有一個(gè)ActionInvocation 類(lèi)型的參數(shù),該參數(shù)內(nèi)部引用了具體的action實(shí)例對(duì)象(如果該action還有其他攔截器的話(huà)),我們可以調(diào)用該參數(shù)的invoke方法調(diào)用具體action實(shí)例的execute方法或者調(diào)用下一個(gè)攔截器,intercept方法返回一個(gè)String 類(lèi)型的字符串代表了具體視圖頁(yè)面。下面看個(gè)具體的例子:
public class TestAction extends ActionSupport { public String execute(){ System.out.println("執(zhí)行execute方法......"); return SUCCESS; } }
public class MyIntercept implements Interceptor { public void init() {} public void destroy() {} public String intercept(ActionInvocation action) throws Exception{ System.out.println("攔截action開(kāi)始......."); String result = action.invoke(); System.out.println("攔截action結(jié)束......."); return result; } }
省略了配置攔截器和TestAction 的代碼,下圖是上述程序運(yùn)行的結(jié)果截圖:
三、配置和引用攔截器
上述的示例定義了一個(gè)簡(jiǎn)單的攔截器實(shí)現(xiàn)類(lèi),我們省略了在struts.xml中配置和引用該攔截器的代碼,本小節(jié)將詳細(xì)的介紹如何在struts.xml中定義和引用我們自定義實(shí)現(xiàn)的攔截器類(lèi)。
從struts-default.xml中我們可以看出來(lái),我們使用<interceptors>元素定義攔截器name和物理位置的配對(duì),例如:
<interceptors> <interceptor name="test" class="MyPackage.TestAction"/> ...... ...... </interceptors>
上述代碼定義了一個(gè)攔截器test,它對(duì)應(yīng)于具體的一個(gè)class。需要注意的是,定義攔截器的元素 interceptors 及其子元素必須被配置在某個(gè)package包下。
以上只是定義了一個(gè)攔截器和具體攔截器實(shí)現(xiàn)類(lèi)之間的映射關(guān)系,但是想要實(shí)現(xiàn)對(duì)某個(gè)具體的action的攔截需要使用元素<interceptor-ref>根據(jù)name屬性值引用一個(gè)上述已經(jīng)定義了的攔截器。例如:
<action name="test" class="MyPackage.TestAction"> <interceptor-ref name="test"/> <result name="success">/index.jsp</result> ...... ...... </action>
正如上述代碼展示的一樣,該元素用于引用一個(gè)已經(jīng)定義好了的攔截器,并且該元素出現(xiàn)在具體的action內(nèi)部,表明了該action具有一個(gè)test攔截器。以上代碼實(shí)現(xiàn)了對(duì)單個(gè)攔截器的定義和引用,其實(shí)對(duì)于攔截器棧(一堆攔截器的組合)來(lái)說(shuō)配置也是類(lèi)似的。定義一個(gè)攔截器棧的代碼是如下的:
<interceptor-stack name="攔截器棧名"> interceptor-ref name="攔截器一"/> interceptor-ref name="攔截器二"/> interceptor-ref name="攔截器三"/> ..... </interceptor-stack>
引用一個(gè)攔截器棧就沒(méi)什么區(qū)別了:
interceptor-ref name="攔截器棧名"/>
當(dāng)然我們也可以通過(guò)
<default-interceptor-ref name="攔截器名"/>
配置默認(rèn)攔截器或者攔截器棧,如果該包下某個(gè)action沒(méi)有顯式指定攔截器,那么就會(huì)調(diào)用該默認(rèn)攔截器,否則如果顯式配置了攔截器,那么默認(rèn)攔截器將會(huì)失效。
四、為Action中指定方法配置攔截器
在默認(rèn)情況下,我們?yōu)閍ction配置了攔截器之后,該攔截器將會(huì)攔截該action中所有的方法,這有時(shí)候會(huì)給我們帶來(lái)麻煩,當(dāng)然struts為我們提供API用來(lái)針對(duì)具體的某個(gè)方法配置攔截器。這里涉及到一個(gè)抽象類(lèi):MethodFilterInterceptor。該類(lèi)實(shí)際上實(shí)現(xiàn)了Interceptor并完成了一些默認(rèn)實(shí)現(xiàn),我們簡(jiǎn)單看看其中的代碼:
public abstract class MethodFilterInterceptor extends AbstractInterceptor { //該set集合保存了該攔截器不需要攔截的所有方法 protected Set<String> excludeMethods = Collections.emptySet(); //該set集合保存了所有該攔截器需要攔截的方法 protected Set<String> includeMethods = Collections.emptySet(); //省略getter,setter方法 //用于攔截action的入口 public String intercept(ActionInvocation invocation) throws Exception { if (applyInterceptor(invocation)) { return doIntercept(invocation); } return invocation.invoke(); } //判斷當(dāng)前需要調(diào)用的action處理邏輯方法是否需要被此攔截器攔截 protected boolean applyInterceptor(ActionInvocation invocation) { String method = invocation.getProxy().getMethod(); boolean applyMethod = MethodFilterInterceptorUtil.applyMethod(this.excludeMethods, this.includeMethods, method); if ((this.log.isDebugEnabled()) && (!applyMethod)) { this.log.debug("Skipping Interceptor... Method [" + method + "] found in exclude list.", new String[0]); } return applyMethod; } //這是需要我們重寫(xiě)的方法,具體作用下文介紹 protected abstract String doIntercept(ActionInvocation paramActionInvocation) throws Exception; }
從上述代碼中可以看出,該抽象類(lèi)實(shí)現(xiàn)了Interceptor接口并完成了基本的實(shí)現(xiàn)。除此之外,該類(lèi)提供了兩個(gè)集合用于保存該攔截器需要攔截的所有方法和不需要攔截的所有方法,攔截器入口intercept中會(huì)首先判斷此次請(qǐng)求action實(shí)例中的邏輯處理方法是否需要被該攔截器攔截,如果需要被攔截,那么將會(huì)調(diào)用doIntercept我們自己實(shí)現(xiàn)的攔截器邏輯。否則直接調(diào)用invoke方法執(zhí)行處理邏輯。所以一般來(lái)說(shuō),我們只需要重寫(xiě)doIntercept方法完成攔截器的核心處理即可。
當(dāng)然此處需要注意一點(diǎn)的是,用于判斷當(dāng)前請(qǐng)求的處理邏輯方法是否需要被該攔截器攔截的方法applyInterceptor是在intercept中進(jìn)行校驗(yàn)的,也就是說(shuō)在執(zhí)行doIntercept方法之前excludeMethods和includeMethods的值應(yīng)當(dāng)是已經(jīng)初始化完畢了的。所以我們?cè)赿oIntercept中再次為這兩個(gè)屬性賦值是沒(méi)用的,因?yàn)橐呀?jīng)完成了校驗(yàn)。一般我們?cè)趕truts.xml中為這兩個(gè)屬性賦值,因?yàn)樵撆渲梦募窍缺患虞d的。下面我們看個(gè)實(shí)例:
//自定義一個(gè)攔截器 public class MyIntercept extends MethodFilterInterceptor { protected String doIntercept(ActionInvocation action) throws Exception{ System.out.println("攔截開(kāi)始......"); String result = action.invoke(); System.out.println("攔截結(jié)束......"); return result; } }
//引用該攔截器并指定不需要攔截的方法 <action name="test" class="MyPackage.TestAction"> <interceptor-ref name="test"> <param name="excludeMethods">execute</param> </interceptor-ref> <result name="success">/index.jsp</result> </action>
下面我們看運(yùn)行的結(jié)果截圖:
顯然我們指明了該攔截器不用攔截方法execute,當(dāng)然結(jié)果顯示的也是如我們所愿。如果我們修改上述struts.xml中內(nèi)容:
<action name="test" class="MyPackage.TestAction"> <interceptor-ref name="test"> <param name="includeMethods">execute</param> </interceptor-ref> <result name="success">/index.jsp</result> </action>
我們指定該execute方法是需要被攔截器攔截的,下面運(yùn)行的結(jié)果截圖:
當(dāng)然如果需要指定多個(gè)方法需要被攔截或者不用被攔截,可以使用英文逗號(hào)隔開(kāi)這些方法,例如:
<param name="includeMethods">方法一,方法二,方法三</param>
最后還有一點(diǎn)是:如果一個(gè)方法既被放在了includeMethods中也被放在了excludeMethods中,那么框架將會(huì)選擇攔截該方法。
五、有關(guān)攔截器機(jī)制的其他一些細(xì)節(jié)
攔截器的執(zhí)行順序是按照引用攔截器的順序決定的,例如我們定義兩個(gè)攔截器:
<action name="test" class="MyPackage.TestAction"> <interceptor-ref name="test"/> <interceptor-ref name="test2"/> <result name="success">/index.jsp</result> </action>
也就是說(shuō)第一個(gè)攔截器攔截action之后,會(huì)調(diào)用invoke方法,如果還有其他攔截器則會(huì)調(diào)用下一個(gè)攔截器,一層層嵌套,最后結(jié)束最外層的攔截器。
上述實(shí)例中我們使用param參數(shù)為攔截器類(lèi)中的includeMethods屬性賦值,但是如果是一個(gè)攔截器棧中我們有該如何為其中某個(gè)具體的攔截器屬性賦值呢?
<interceptor-ref name="攔截器棧"> <param name="攔截器一.屬性名">屬性值</param> </interceptor-ref>
看完上述內(nèi)容是否對(duì)您有幫助呢?如果還想對(duì)相關(guān)知識(shí)有進(jìn)一步的了解或閱讀更多相關(guān)文章,請(qǐng)關(guān)注創(chuàng)新互聯(lián)行業(yè)資訊頻道,感謝您對(duì)創(chuàng)新互聯(lián)的支持。
分享名稱(chēng):Struts2攔截器的實(shí)現(xiàn)原理是什么
文章轉(zhuǎn)載:http://jinyejixie.com/article10/ipiego.html
成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供移動(dòng)網(wǎng)站建設(shè)、App開(kāi)發(fā)、標(biāo)簽優(yōu)化、ChatGPT、云服務(wù)器、靜態(tài)網(wǎng)站
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶(hù)投稿、用戶(hù)轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話(huà):028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來(lái)源: 創(chuàng)新互聯(lián)