【Struts2】:攔截器實現方法過濾

連江偉發表於2016-05-31

        眾所周知,我們在使用Struts2進行專案開發的時候,如果為某個Action配置攔截器,那麼這個攔截器就會攔截該Action內的所有方法。但是在有些情況下,我們不需要攔截所有的方法,只想攔截指定的方法,此時就需要用到Struts2攔截器的方法過濾的特性了。

        為了實現方法過濾的特性,Struts2提供了一個MethodFilterInterceptor類,該類是AbstractInterceptor類的子類,如果想要自己實現的攔截器支援方法過濾特性,那就要繼承MethodFilterInterceptor。

        MethodFilterInterceptor類重寫了AbstractInterceptor類的intercept方法,但是提供了一個doIntercept抽象方法。從這種設計方法可以看出,MethodFilterInterceptor類的intercept已經實現了對Action的攔截行為,但是真正的攔截邏輯還需要開發者自己來寫,也就是通過回撥dointercept方法實現。可見,如果我們想要實現自己的攔截邏輯,則應該重寫doIntercept方法。

        下面我們通過一個簡單的方法過濾示例,來展示如何實現方法過濾,具體程式碼如下:

// 攔截方法的攔截器,應該繼承MethodFilterInterceptor抽象類
public class MyFilterInterceptor
	extends MethodFilterInterceptor
{
	// 簡單攔截器的名字
	private String name;
	// 為該簡單攔截器設定名字的setter方法
	public void setName(String name)
	{
		this.name = name;
	}
	// 重寫doIntercept()方法,實現對Action的攔截邏輯
	public String doIntercept(ActionInvocation invocation)
		throws Exception
	{
		// 取得被攔截的Action例項
		LoginAction action = (LoginAction)invocation.getAction();
		// 列印執行開始的時間
		System.out.println(name + " 攔截器的動作---------"
			+ "開始執行登入Action的時間為:" + new Date());
		// 取得開始執行Action的時間
		long start = System.currentTimeMillis();
		// 執行該攔截器的後一個攔截器,或者直接指定Action的被攔截方法
		String result = invocation.invoke();
		// 列印執行結束的時間
		System.out.println(name + " 攔截器的動作---------"
			+ "執行完登入Action的時間為:" + new Date());
		long end = System.currentTimeMillis();
		// 列印執行該Action所花費的時間
		System.out.println(name + " 攔截器的動作---------"
			+ "執行完該Action的時間為" + (end - start) + "毫秒");
		return result;
	}
}

        從上面的程式碼可以看出,上面的攔截邏輯與普通的攔截器的攔截邏輯並無多大差別,只是重寫的方法不一樣而已。需要注意的地方是:要想實現方法過濾的特性,必須繼承MethodFilterInterceptor抽象類,並且重寫doIntercept方法定義對Action的攔截邏輯。

        在MethodFilterInterceptor的方法中,增加了兩個方法:

        SetExcludeMethods:排除需要過濾的方法,即設定方法的“黑名單”,在該方法引數裡列舉出來的方法都不會被攔截。

        SetIncludeMethods:設定需要過濾的方法,即設定方法的“白名單”,在該方法的引數裡列出的方法都會被攔截。

        因為MethodFilterInterceptor類包含了如上的兩個方法,則其子類也會獲得這兩個方法,因此我們可以在配置檔案struts.xml中指定需要或者不需要被攔截的方法。

<package name="lee" extends="struts-default">
	<!-- 應用所需使用的攔截器都在該元素下配置 -->
	<interceptors>
		<!-- 配置mySimple攔截器 -->
		<interceptor name="mySimple"
		class="org.ljw.app.interceptor.MyFilterInterceptor">
			<!-- 為攔截器指定引數值 -->
			<param name="name">攔截方法的攔截器</param>
		</interceptor>
	</interceptors>

	<action name="login" class="org.ljw.app.action.LoginAction">
		<result name="error">/WEB-INF/content/error.jsp</result>
		<result>/WEB-INF/content/welcome.jsp</result> 
		<!-- 配置系統的預設攔截器 -->
		<interceptor-ref name="defaultStack"/>
		<!-- 應用自定義的mySimple攔截器 -->
		<interceptor-ref name="mySimple">
			<!-- 重新指定name屬性的屬性值 -->
			<param name="name">改名後的攔截方法過濾攔截器</param>
			<!-- 指定execute方法不需要被攔截 -->
			<param name="excludeMethods">execute</param>
		</interceptor-ref>
	</action>
	<action name="*">
		<result>/WEB-INF/content/{1}.jsp</result>
	</action>
</package>

        上面的配置檔案中使用了攔截器引數excludeMethods制定了execute方法不用被攔截,如果需要同時指定多個方法不被攔截器攔截,則可以使用英文逗號將其隔開即可。另外如果出現同一個方法名同時出現在excludeMethods和includeMethods中,即二者產生衝突,最終以IncludeMethods引數指定的為準,也就是衝突的情況下,預設是唄攔截的,當然了我相信大家不會出現這種矛盾的。

相關文章