第六節:Struts2-攔截器

一。介紹攔截器

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










發佈了44 篇原創文章 · 獲贊 13 · 訪問量 3萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章