攔截器
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è)詞大家應(yīng)該知道——攔截器鏈(Interceptor Chain,在Struts 2中稱(chēng)為攔截器棧Interceptor Stack)。攔截器鏈就是將攔截器按一定的順序聯(lián)結(jié)成一條鏈。在訪問(wèn)被攔截的方法或字段時(shí),攔截器鏈中的攔截器就會(huì)按其之前定義的順序被調(diào)用。
2、實(shí)現(xiàn)原理
Struts 2的攔截器實(shí)現(xiàn)相對(duì)簡(jiǎn)單。當(dāng)請(qǐng)求到達(dá)Struts 2的ServletDispatcher時(shí),Struts 2會(huì)查找配置文件,并根據(jù)其配置實(shí)例化相對(duì)的攔截器對(duì)象,然后串成一個(gè)列表(list),最后一個(gè)一個(gè)地調(diào)用列表中的攔截器,如圖所示。
圖1 攔截器調(diào)用序列圖
?
?
3、已有的攔截器
Struts 2已經(jīng)為您提供豐富多樣的,功能齊全的攔截器實(shí)現(xiàn)。大家可以到struts2-all-2.0.1.jar或struts2-core.jar包的
struts-default.xml查看關(guān)于默認(rèn)的攔截器與攔截器鏈的配置
。
以下部分就是從struts-default.xml文件摘取的內(nèi)容:
< interceptor name ="alias" class ="com.opensymphony.xwork2.interceptor.AliasInterceptor" />
< interceptor name ="autowiring" class ="com.opensymphony.xwork2.spring.interceptor.ActionAutowiringInterceptor" />
< interceptor name ="chain" class ="com.opensymphony.xwork2.interceptor.ChainingInterceptor" />
< interceptor name ="conversionError" class ="org.apache.struts2.interceptor.StrutsConversionErrorInterceptor" />
< interceptor name ="createSession" class ="org.apache.struts2.interceptor.CreateSessionInterceptor" />
< interceptor name ="debugging" class ="org.apache.struts2.interceptor.debugging.DebuggingInterceptor" />
< interceptor name ="external-ref" class ="com.opensymphony.xwork2.interceptor.ExternalReferencesInterceptor" />
< interceptor name ="execAndWait" class ="org.apache.struts2.interceptor.ExecuteAndWaitInterceptor" />
< interceptor name ="exception" class ="com.opensymphony.xwork2.interceptor.ExceptionMappingInterceptor" />
< interceptor name ="fileUpload" class ="org.apache.struts2.interceptor.FileUploadInterceptor" />
< interceptor name ="i18n" class ="com.opensymphony.xwork2.interceptor.I18nInterceptor" />
< interceptor name ="logger" class ="com.opensymphony.xwork2.interceptor.LoggingInterceptor" />
< interceptor name ="model-driven" class ="com.opensymphony.xwork2.interceptor.ModelDrivenInterceptor" />
< interceptor name ="scoped-model-driven" class ="com.opensymphony.xwork2.interceptor.ScopedModelDrivenInterceptor" />
< interceptor name ="params" class ="com.opensymphony.xwork2.interceptor.ParametersInterceptor" />
< interceptor name ="prepare" class ="com.opensymphony.xwork2.interceptor.PrepareInterceptor" />
< interceptor name ="static-params" class ="com.opensymphony.xwork2.interceptor.StaticParametersInterceptor" />
< interceptor name ="scope" class ="org.apache.struts2.interceptor.ScopeInterceptor" />
< interceptor name ="servlet-config" class ="org.apache.struts2.interceptor.ServletConfigInterceptor" />
< interceptor name ="sessionAutowiring" class ="org.apache.struts2.spring.interceptor.SessionContextAutowiringInterceptor" />
< interceptor name ="timer" class ="com.opensymphony.xwork2.interceptor.TimerInterceptor" />
< interceptor name ="token" class ="org.apache.struts2.interceptor.TokenInterceptor" />
< interceptor name ="token-session" class ="org.apache.struts2.interceptor.TokenSessionStoreInterceptor" />
< interceptor name ="validation" class ="com.opensymphony.xwork2.validator.ValidationInterceptor" />
< interceptor name ="workflow" class ="com.opensymphony.xwork2.interceptor.DefaultWorkflowInterceptor" />
< interceptor name ="store" class ="org.apache.struts2.interceptor.MessageStoreInterceptor" />
< interceptor name ="checkbox" class ="org.apache.struts2.interceptor.CheckboxInterceptor" />
< interceptor name ="profiling" class ="org.apache.struts2.interceptor.ProfilingActivationInterceptor" />
?
4、配置和使用攔截器
在struts-default.xml中已經(jīng)配置了以上的攔截器。如果您想要使用上述攔截器,只需要在應(yīng)用程序struts.xml文件中通過(guò)“<include file="struts-default.xml" />”將struts-default.xml文件包含進(jìn)來(lái),并繼承其中的struts-default包(package),最后在定義Action時(shí),使用“<interceptor-ref name="xx" />”引用攔截器或攔截器棧(interceptor stack)。一旦您繼承了struts-default包(package),所有Action都會(huì)調(diào)用攔截器棧 ——defaultStack。當(dāng)然,在Action配置中加入“<interceptor-ref name="xx" />”可以覆蓋defaultStack。
5、自定義攔截器
作為“框架(framework)”,可擴(kuò)展性是不可或缺的,因?yàn)槭郎蠜](méi)有放之四海而皆準(zhǔn)的東西。雖然,Struts 2為我們提供如此豐富的攔截器實(shí)現(xiàn),但是這并不意味我們失去創(chuàng)建自定義攔截器的能力,恰恰相反,在Struts 2自定義攔截器是相當(dāng)容易的一件事。
?
???
大家在開(kāi)始著手創(chuàng)建自定義攔截器前,切記以下原則:
攔截器必須是無(wú)狀態(tài)的,不要使用在API提供的ActionInvocation之外的任何東西。
要求攔截器是無(wú)狀態(tài)的原因是Struts 2不能保證為每一個(gè)請(qǐng)求或者action創(chuàng)建一個(gè)實(shí)例,所以如果攔截器帶有狀態(tài),會(huì)引發(fā)并發(fā)問(wèn)題。
所有的Struts 2的攔截器都直接或間接實(shí)現(xiàn)接口
com.opensymphony.xwork2.interceptor.Interceptor
。除此之外,大家可能更喜歡繼承類(lèi)com.opensymphony.xwork2.interceptor.
AbstractInterceptor
。
6、使用Token攔截器控制重復(fù)提交
jsp:
<form action="user" method="post">
name:<input name="name">
age:<input name="age">
<input type="submit" value="add">
<s:token></s:token>
</form>
生成的html:
<form action="user" method="post">
name:<input name="name">
age:<input name="age">
<input type="submit" value="add">
<input type="hidden" name="struts.token.name" value="struts.token" />
<input type="hidden" name="struts.token" value="85PAL2KOFS09RKVAP1FFBB985BJEGEUQ" />
</form>
?
其中token為令牌,服務(wù)端生成存儲(chǔ)在session中并寫(xiě)入客戶(hù)端頁(yè)面,等用戶(hù)提交form表單時(shí)會(huì)攜帶token,服務(wù)器比對(duì)token是否相同,相同則成功提交,并清除session中的token,如再重復(fù)提交服務(wù)端發(fā)現(xiàn)session中token已經(jīng)沒(méi)有了即失效,便返回Token失效頁(yè)面。
?
Struts.xml:
<action name="user" class="com.bjsxt.action.UserAction">
<result>/addOK.jsp</result>
<interceptor-ref name="defaultStack"></interceptor-ref>
<interceptor-ref name="token"></interceptor-ref>
<result name="invalid.token">/error.jsp</result>
</action>
?
其中增加token的攔截器,會(huì)覆蓋默認(rèn)的defaultStack攔截器,所以需要再加上defaultStack在token前面,主要用來(lái)接收數(shù)據(jù)、聲明異常、國(guó)際化等等攔截器功能。
如果出現(xiàn)重復(fù)提交,即點(diǎn)擊多次add提交按鈕,提交了多次,則后臺(tái)認(rèn)為token無(wú)效,返回error.jsp頁(yè)面。
更多文章、技術(shù)交流、商務(wù)合作、聯(lián)系博主
微信掃碼或搜索:z360901061
微信掃一掃加我為好友
QQ號(hào)聯(lián)系: 360901061
您的支持是博主寫(xiě)作最大的動(dòng)力,如果您喜歡我的文章,感覺(jué)我的文章對(duì)您有幫助,請(qǐng)用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點(diǎn)擊下面給點(diǎn)支持吧,站長(zhǎng)非常感激您!手機(jī)微信長(zhǎng)按不能支付解決辦法:請(qǐng)將微信支付二維碼保存到相冊(cè),切換到微信,然后點(diǎn)擊微信右上角掃一掃功能,選擇支付二維碼完成支付。
【本文對(duì)您有幫助就好】元

