一。介紹攔截器
1.理解DRY規則:在軟件開發領域,現在有一條非常重要的規則:Don't Repeat yoursIf,就是所謂的DRY規則,意思就是不要書寫重複的代碼。
2.Struts2的攔截器機制與動態代理機制相同。動態代理介紹參考:http://blog.csdn.net/a85820069/article/details/17418887
二。攔截器定義配置
1.在struts.xml中配置攔截器
說明:<interceptor>標籤用於定義攔截器。
說明:<param>標籤用於爲攔截器的屬性設定初始值。
注意:在struts.xml文件中定義標籤的出現順序有要求,interceptors標籤必須定義在action標籤之前。如果順序錯亂將會提示如下錯誤信息:
The content of element type "package" must match "(result-types?,interceptors?,default-interceptor-ref?,default-action-ref?,default-class-ref?,global-results?,global-exception-mappings?,action*)"
<!-- 定義攔截器 -->
<interceptors>
<interceptor name="simple" class="intercepter.SimpleInterceptor">
<param name="name">小攔截器(定義位置A)</param>
</interceptor>
</interceptors>
2.在struts.xml中配置攔截器棧
在攔截器棧中可以包含攔截器也可以包含其他攔截器棧
<interceptor-stack name="攔截器棧名">
<interceptor-ref name="攔截器一"></interceptor-ref>
<interceptor-ref name="攔截器二"></interceptor-ref>
<interceptor-ref name="攔截器棧一"></interceptor-ref>
</interceptor-stack>
在攔截器棧中攔截器可以重複,重複的攔截器一樣會順序執行多次。
三。攔截器應用配置1.包與攔截器的關係:
在struts-default.xml文件中有如下配置:
<default-interceptor-ref name="defaultStack"/>
實現了爲struts-default包及其子包中所有action均使用defaultStack作爲默認的攔截器棧。
2.action與攔截器的關係
在action定義中配置使用攔截器
說明:<interceptor-ref>標籤用於引入攔截器。
說明:<param>標籤用於爲攔截器的屬性設定初始值。
<action name="Login" class="action.LoginAction">
<interceptor-ref name="攔截器(棧)名稱">
<param name="參數名">參數值</param>
</interceptor-ref>
<interceptor-ref name="攔截器(棧)名稱">
<param name="參數名">參數值</param>
</interceptor-ref>
<result name="input">/Login.jsp</result>
<result name="success" >/welcome.jsp</result>
<result name="error" >/error.jsp</result>
</action>
注意:
param是否支持動態賦值?比如${屬性名.屬性名}
action指定了攔截器棧(abc)後,將會執行abc攔截規則,與默認指定的defaultStack規則無關。要考慮好是否真的不需要使用defaultStack攔截器棧中的攔截器規則。
在action中可以配置重複的攔截器或攔截器棧,重複的攔截器一樣會順序執行多次。
四。攔截器的屬性初始值的設定可以在定義時進行設定,也可在action中設定。action中的值會覆蓋掉在定義時的值。
五。攔截器的執行順序
攔截器包含“在目標方法之前執行的方法”以及“在目標方法執行之後執行的方法”
假設攔截器棧定義如下
<攔截器棧一>
攔截器一
攔截器二
攔截器三
攔截器棧二
<攔截器棧一/>
<攔截器棧二>
攔截器一
攔截器四
攔截器五
<攔截器棧二/>
則執行順序爲
攔截器棧一.攔截器一.之前執行的方法
攔截器棧一.攔截器二.之前執行的方法
攔截器棧一.攔截器三.之前執行的方法
攔截器棧二.攔截器一.之前執行的方法
攔截器棧二.攔截器四.之前執行的方法
攔截器棧二.攔截器五.之前執行的方法
目標方法
攔截器棧二.攔截器五.之後執行的方法
攔截器棧二.攔截器四.之後執行的方法
攔截器棧二.攔截器一.之後執行的方法
攔截器棧一.攔截器三.之後執行的方法
攔截器棧一.攔截器二.之後執行的方法
攔截器棧一.攔截器一.之後執行的方法
六。介紹與攔截器相關的標籤
<interceptors.../>元素:該元素用於定義攔截器,所有的攔截器和攔截器棧都在該元素下定義。該元素包含<interceptor.../>和<interceptor-stack.../>子元素,分別用於定義攔截器和攔截器棧。
<interceptor.../>元素:該元素用於定義攔截器,定義攔截器時只需指定兩個屬性:name和class,分別指定攔截器名稱和實現類。
<interceptor-stack.../>元素:該元素用於dingyi8攔截器引用,該元素中包含多個<interceptor-ref.../>元素,用於將多個攔截器或者攔截器棧組合成一個新的攔截器棧。
<interceptor-ref.../>元素:該元素引用一個攔截器或者攔截器棧,該元素只需指定一個name屬性,該屬性值爲一個已經定義的攔截和攔截器棧。該元素可以作爲<interceptor-stack.../>和<action.../>元素的子元素使用。
<param.../>元素:該元素用於爲攔截器指定參數,可以作爲<interceptor.../>和<interceptor-ref.../>元素的子元素使用。
七。編寫自定義攔截器
方式一:自定義攔截器應實現:com.opensymphony.xwork2.interceptor.Interceptor接口,該接口包含如下定義
//銷燬該攔截器之前的回調方法
void destroy();
//初始化該攔截器的回調方法
void init();
//攔截器實現攔截的邏輯方法
String intercept(ActionInvocation invocation) throws Exception;
方法說明:
init:在該攔截器被初始化之後,在該攔截器執行攔截之前,系統將回調該方法。對於每個攔截器而言,該init()方法只執行一次。因此,該方法的方法體主要用於打開一些一次性資源,例如數據庫資源等。
destroy:該方法與init()方法對應,在攔截器實例被銷燬之前,系統將回調該攔截器的destroy方法,該方法用於毀掉在init()方法裏打開的資源。
intercept:該方法是用戶需要實現的攔截器動作。就像Action的execute方法一樣,intercept方法會返回一個字符串作爲邏輯視圖。如果該方法直接返回了一個字符串,系統將會跳轉到該邏輯視圖對應的實際視圖資源,不會調用被攔截的Action。該方法的ActionInvocation參數包含了被攔截的Action的引用,可以通過調用該參數的invoke方法,將控制權轉給下一個攔截器,或者轉給Action的execute方法。
方式二:繼承AbstractInterceptor類,該類提供了一個init()和destroy方法的空實現,如果我們實現的攔截器不需要申請資源,則可以無需實現這兩個方法。
編寫action代碼
package intercepter;
import java.util.Date;
import action.FileDownAction;
import com.opensymphony.xwork2.ActionInvocation;
import com.opensymphony.xwork2.interceptor.AbstractInterceptor;
public class SimpleInterceptor extends AbstractInterceptor{
//簡單攔截器的名字(由配置文件提供)
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String intercept(ActionInvocation actionInvocation) throws Exception {
//獲取被攔截的Action實例
FileDownAction action = (FileDownAction)actionInvocation.getAction();
//打印
System.out.println(name+"攔截器的動作---------------" +
"開始執行下載Action的時間爲:" + new Date());
//取得開始執行Action的時間
long start = System.currentTimeMillis();
//執行該攔截器的後一個攔截器,或者執行執行Action的execute方法
String returnStr = actionInvocation.invoke();
System.out.println(name+"攔截器的動作------------------" +
"執行完下載Action的時間爲:" + new Date());
//取得執行完的時間
long end = System.currentTimeMillis();
System.out.println(name+"攔截器的動作-----------------" +
"執行完該Action的時間爲" + (end - start) + "毫秒");
return returnStr;
}
}
編寫struts.xml文件:
說明:對Action沒有要求,任何實現的Action均可,所以不對action進行代碼說明。
<!DOCTYPE struts PUBLIC "-//Apache Software Foundation//DTD Struts Configuration 2.0//EN" "http://struts.apache.org/dtds/struts-2.0.dtd">
<struts>
<package name="loginAction" namespace="/x" extends="struts-default">
<!-- 定義攔截器 -->
<interceptors>
<interceptor name="simple" class="intercepter.SimpleInterceptor">
<param name="name">小攔截器(定義位置A)</param>
</interceptor>
</interceptors>
<action name="MydownFile" class="action.FileDownAction">
<interceptor-ref name="defaultStack"></interceptor-ref>
<interceptor-ref name="simple">
<param name="name">小攔截器(定義位置B)</param>
</interceptor-ref>
<!-- 動態配置下載文件路徑 -->
<param name="inputPath">\down\1.gif</param>
<result name="success" type="stream">
<!-- 指定下載文件的文件類型 -->
<param name="contentType">image/gif</param>
<!-- 指定下載文件的文件位置 -->
<param name="inputName">targetFile</param>
<param name="contentDisposition">attachment;filename="中文名可以不?.gif"</param>
<!-- 指定下載文件的緩衝大小 -->
<param name="bufferSize">4096</param>
</result>
</action>
</package>
</struts>
運行後輸出的結果:
說明:根據以下輸出說明攔截器生效了。
說明:根據name輸出的 "小攔截器(定義位置B)"說明action中爲攔截器設定的參數生效了。
小攔截器(定義位置B)攔截器的動作---------------開始執行下載Action的時間爲:Wed Jan 22 02:34:55 CST 2014
小攔截器(定義位置B)攔截器的動作------------------執行完下載Action的時間爲:Wed Jan 22 02:34:57 CST 2014
小攔截器(定義位置B)攔截器的動作-----------------執行完該Action的時間爲1911毫秒
方式三:帶方法過濾的攔截器
爲了實現方法過濾的特性,Struts2提供了一個MethodFilterInterceptor類,該類是AbstractInterceptor類的子類,如果用戶需要自己實現攔截器支持方法過濾特性,則應該繼承MethodFilterInterceptor。
MethodFilterInterceptor類重寫了 AbstractInterceptor類的intercept(ActionInvocation invocation)方法,但提供了一個doInterccept(ActionInvocation invocation)抽象方法需要用戶編寫。
在MethodFilterInterceptor方法中,額外增加了如下兩個方法:
public void setExcludeMethods(String excludeMethods);排除需要過濾的方法——設置方法“黑名單”,所有在excludeMethods字符串中列出的方法都不會被攔截。
public void setIncludeMethods(String includeMethods);設置需要過濾的方法——設置方法“白名單”,所有在includeMethods字符串中列出的方法都會被攔截。
注意:如果一個方法同時在excludeMethods和includeMethods中列出,則該方法會被攔截。
在配置文件中使用param標籤爲excludeMethods和includeMethods參數賦值。
八。攔截結果的監聽器
在攔截器中可以手動爲攔截器注入一個由PreResultListener接口的實現類對象。在攔截器中返回結果字符串後調用該對象的beforeResult(ActionInvocation invocation,String resultCode)方法。此方法在攔截器之後執行的方法之前執行。
注意:不要在beforeResult方法中調用invocation對象的invoke方法,如果調用了將會再次執行Action處理,Action處理之後緊跟的是BeforResult方法——這是一個死循環。
九。覆蓋攔截器中特定攔截器的參數
如何爲攔截器棧中某一個攔截器設定參數值,參照如下配置
<interceptor-ref name="defaultStack">
<param name="i18n.name">GBK</param>
</interceptor-ref>
<攔截器名稱>.<參數名>
十。Struts2內建攔截器介紹
alias:實現在不同請求中相似參數別名的轉換。
autowiring:這是個自動裝配的攔截器,主要用於當Struts2和Spring整合時,Struts2可以使用自動裝配的方式來訪問Spring容器中的Bean。
chain:構建一個Action鏈,使當前Action可以訪問前一個Action的屬性,一般和<result type="chain".../>一起使用。
conversionError:這是一個負責處理類型轉換錯誤的攔截器,它負責將類型轉換錯誤從ActionContext中取出,並轉換成Action的FieldError錯誤。
createSession:該攔截器負責創建一個HttpSession對象,主要用於那些需要有HttpSession對象才能正常工作的攔截器中。
debuggingg:當使用Struts2的開發模式時,這個攔截器會提供更多的調試信息。
execAndWait:這個攔截器負責處理異常,它將異常映射爲結果。
exception:這個攔截器負責處理異常,它將異常映射爲結果。
fileupload:這個攔截器主要用於文件上傳,它負責解析表單中文件域的內容。
il8n:這是支持國際化的攔截器,它負責把所選的語言、區域放入用戶Session中。
logger:這是一個負責日誌記錄的攔截器,主要是輸出Action的名字。
model-driven:這是一個用於模型驅動的攔截器,當某個Action類實現了ModelDriven接口時,它負責把getModel()方法的結果堆入ValueStack中。
scoped-model-driven:如果一個Action實現了一個ScopedModelDriven接口,該攔截器負責從指定生存範圍中找出指定的Model,並將通過setModel方法將該Model傳給Action實例。
params:這是最基本的一個攔截器,它負責解析HTTP請求中的參數,並將參數值設置成Action對應的屬性值。
prepare:如果action實現了Preparable接口,將會調用該攔截器的prepare()方法。
static-params:這個攔截器負責將xml中<action>標籤下<param>標籤中的參數傳入action。
scope:這是範圍轉換攔截器,它可以將Action狀態信息保存到HttpSession範圍,或者保存到ServletContext範圍內。
servlet-config:如果某個Action需要直接訪問Servlet API,就是通過這個攔截器實現的。
roles:這是一個JAAS(Java Authentication and Authorization Service,Java授權和認證服務)攔截器,只有當瀏覽者取得合適的授權後,纔可以調用被該攔截器攔截的Action。
timer:這個攔截器負責輸出Action的執行時間,這個攔截器在分析該Action的性能瓶頸時比較有用。
token:這個攔截器主要用於阻止重複提交,它檢查傳到Action中的token,從而防止多次提交。
token-session :這個攔截器的作用與前一個基本類似,只是它把token保存在HttpSession中。
validation:通過執行在xxxAction-validation.xml中定義的校驗器,從而完成數據校驗。
workflow:這個攔截器負責調用Action類中的validate方法,如果校驗失敗,則返回input的邏輯視圖。
如果攔截器配置中引用了未知的攔截器名則啓動時錯誤信息如下:
嚴重: Dispatcher initialization failed
Unable to load configuration. - interceptor-ref - file:/G:/apache-tomcat-6.0.13/webapps/struts2HelloWorld/WEB-INF/classes/struts.xml:12:34
at com.opensymphony.xwork2.config.ConfigurationManager.getConfiguration(ConfigurationManager.java:70)
at org.apache.struts2.dispatcher.Dispatcher.init_PreloadConfiguration(Dispatcher.java:446)
at org.apache.struts2.dispatcher.Dispatcher.init(Dispatcher.java:490)
at org.apache.struts2.dispatcher.FilterDispatcher.init(FilterDispatcher.java:193)
at org.apache.catalina.core.ApplicationFilterConfig.getFilter(ApplicationFilterConfig.java:275)
at org.apache.catalina.core.ApplicationFilterConfig.setFilterDef(ApplicationFilterConfig.java:397)
at org.apache.catalina.core.ApplicationFilterConfig.<init>(ApplicationFilterConfig.java:108)
at org.apache.catalina.core.StandardContext.filterStart(StandardContext.java:3693)
at org.apache.catalina.core.StandardContext.start(StandardContext.java:4340)
at org.apache.catalina.core.ContainerBase.addChildInternal(ContainerBase.java:791)
at org.apache.catalina.core.ContainerBase.addChild(ContainerBase.java:771)
at org.apache.catalina.core.StandardHost.addChild(StandardHost.java:525)
at org.apache.catalina.startup.HostConfig.deployDirectory(HostConfig.java:920)
at org.apache.catalina.startup.HostConfig.deployDirectories(HostConfig.java:883)
at org.apache.catalina.startup.HostConfig.deployApps(HostConfig.java:492)
at org.apache.catalina.startup.HostConfig.start(HostConfig.java:1138)
at org.apache.catalina.startup.HostConfig.lifecycleEvent(HostConfig.java:311)
at org.apache.catalina.util.LifecycleSupport.fireLifecycleEvent(LifecycleSupport.java:117)
at org.apache.catalina.core.ContainerBase.start(ContainerBase.java:1053)
at org.apache.catalina.core.StandardHost.start(StandardHost.java:719)
at org.apache.catalina.core.ContainerBase.start(ContainerBase.java:1045)
at org.apache.catalina.core.StandardEngine.start(StandardEngine.java:443)
at org.apache.catalina.core.StandardService.start(StandardService.java:516)
at org.apache.catalina.core.StandardServer.start(StandardServer.java:710)
at org.apache.catalina.startup.Catalina.start(Catalina.java:566)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
at org.apache.catalina.startup.Bootstrap.start(Bootstrap.java:288)
at org.apache.catalina.startup.Bootstrap.main(Bootstrap.java:413)
Caused by: Unable to find interceptor class referenced by ref-name 攔截器名稱 - interceptor-ref - file:/G:/apache-tomcat-6.0.13/webapps/struts2HelloWorld/WEB-INF/classes/struts.xml:12:34
at com.opensymphony.xwork2.config.providers.InterceptorBuilder.constructInterceptorReference(InterceptorBuilder.java:63)
at com.opensymphony.xwork2.config.providers.XmlConfigurationProvider.lookupInterceptorReference(XmlConfigurationProvider.java:1110)
at com.opensymphony.xwork2.config.providers.XmlConfigurationProvider.buildInterceptorList(XmlConfigurationProvider.java:626)
at com.opensymphony.xwork2.config.providers.XmlConfigurationProvider.addAction(XmlConfigurationProvider.java:440)
at com.opensymphony.xwork2.config.providers.XmlConfigurationProvider.addPackage(XmlConfigurationProvider.java:552)
at com.opensymphony.xwork2.config.providers.XmlConfigurationProvider.loadPackages(XmlConfigurationProvider.java:292)
at org.apache.struts2.config.StrutsXmlConfigurationProvider.loadPackages(StrutsXmlConfigurationProvider.java:112)
at com.opensymphony.xwork2.config.impl.DefaultConfiguration.reloadContainer(DefaultConfiguration.java:250)
at com.opensymphony.xwork2.config.ConfigurationManager.getConfiguration(ConfigurationManager.java:67)
... 30 more
2014-1-22 2:33:05 org.apache.catalina.core.StandardContext filterStart
嚴重: Exception starting filter struts2
Unable to load configuration. - interceptor-ref - file:/G:/apache-tomcat-6.0.13/webapps/struts2HelloWorld/WEB-INF/classes/struts.xml:12:34
at org.apache.struts2.dispatcher.Dispatcher.init(Dispatcher.java:502)
at org.apache.struts2.dispatcher.FilterDispatcher.init(FilterDispatcher.java:193)
at org.apache.catalina.core.ApplicationFilterConfig.getFilter(ApplicationFilterConfig.java:275)
at org.apache.catalina.core.ApplicationFilterConfig.setFilterDef(ApplicationFilterConfig.java:397)
at org.apache.catalina.core.ApplicationFilterConfig.<init>(ApplicationFilterConfig.java:108)
at org.apache.catalina.core.StandardContext.filterStart(StandardContext.java:3693)
at org.apache.catalina.core.StandardContext.start(StandardContext.java:4340)
at org.apache.catalina.core.ContainerBase.addChildInternal(ContainerBase.java:791)
at org.apache.catalina.core.ContainerBase.addChild(ContainerBase.java:771)
at org.apache.catalina.core.StandardHost.addChild(StandardHost.java:525)
at org.apache.catalina.startup.HostConfig.deployDirectory(HostConfig.java:920)
at org.apache.catalina.startup.HostConfig.deployDirectories(HostConfig.java:883)
at org.apache.catalina.startup.HostConfig.deployApps(HostConfig.java:492)
at org.apache.catalina.startup.HostConfig.start(HostConfig.java:1138)
at org.apache.catalina.startup.HostConfig.lifecycleEvent(HostConfig.java:311)
at org.apache.catalina.util.LifecycleSupport.fireLifecycleEvent(LifecycleSupport.java:117)
at org.apache.catalina.core.ContainerBase.start(ContainerBase.java:1053)
at org.apache.catalina.core.StandardHost.start(StandardHost.java:719)
at org.apache.catalina.core.ContainerBase.start(ContainerBase.java:1045)
at org.apache.catalina.core.StandardEngine.start(StandardEngine.java:443)
at org.apache.catalina.core.StandardService.start(StandardService.java:516)
at org.apache.catalina.core.StandardServer.start(StandardServer.java:710)
at org.apache.catalina.startup.Catalina.start(Catalina.java:566)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
at org.apache.catalina.startup.Bootstrap.start(Bootstrap.java:288)
at org.apache.catalina.startup.Bootstrap.main(Bootstrap.java:413)
Caused by: Unable to load configuration. - interceptor-ref - file:/G:/apache-tomcat-6.0.13/webapps/struts2HelloWorld/WEB-INF/classes/struts.xml:12:34
at com.opensymphony.xwork2.config.ConfigurationManager.getConfiguration(ConfigurationManager.java:70)
at org.apache.struts2.dispatcher.Dispatcher.init_PreloadConfiguration(Dispatcher.java:446)
at org.apache.struts2.dispatcher.Dispatcher.init(Dispatcher.java:490)
... 28 more
Caused by: Unable to find interceptor class referenced by ref-name 攔截器名稱 - interceptor-ref - file:/G:/apache-tomcat-6.0.13/webapps/struts2HelloWorld/WEB-INF/classes/struts.xml:12:34
at com.opensymphony.xwork2.config.providers.InterceptorBuilder.constructInterceptorReference(InterceptorBuilder.java:63)
at com.opensymphony.xwork2.config.providers.XmlConfigurationProvider.lookupInterceptorReference(XmlConfigurationProvider.java:1110)
at com.opensymphony.xwork2.config.providers.XmlConfigurationProvider.buildInterceptorList(XmlConfigurationProvider.java:626)
at com.opensymphony.xwork2.config.providers.XmlConfigurationProvider.addAction(XmlConfigurationProvider.java:440)
at com.opensymphony.xwork2.config.providers.XmlConfigurationProvider.addPackage(XmlConfigurationProvider.java:552)
at com.opensymphony.xwork2.config.providers.XmlConfigurationProvider.loadPackages(XmlConfigurationProvider.java:292)
at org.apache.struts2.config.StrutsXmlConfigurationProvider.loadPackages(StrutsXmlConfigurationProvider.java:112)
at com.opensymphony.xwork2.config.impl.DefaultConfiguration.reloadContainer(DefaultConfiguration.java:250)
at com.opensymphony.xwork2.config.ConfigurationManager.getConfiguration(ConfigurationManager.java:67)
... 30 more
2014-1-22 2:33:05 org.apache.catalina.core.StandardContext start
嚴重: Error filterStart
2014-1-22 2:33:05 org.apache.catalina.core.StandardContext start
嚴重: Context [/struts2HelloWorld] startup failed due to previous errors