1. 理解攔截器
1.1. 什么是攔截器:
攔截器,在AOP(Aspect-Oriented Programming)中用于在某個方法或字段被訪問之前,進行攔截然后在之前或之后加入某些操作。攔截是AOP的一種實現策略。
在Webwork的中文文檔的解釋為——攔截器是動態攔截Action調用的對象。它提供了一種機制可以使開發者可以定義在一個action執行的前后執行的代碼,也可以在一個action執行前阻止其執行。同時也是提供了一種可以提取action中可重用的部分的方式。
談到攔截器,還有一個詞大家應該知道——攔截器鏈(Interceptor Chain,在Struts 2中稱為攔截器棧Interceptor Stack)。攔截器鏈就是將攔截器按一定的順序聯結成一條鏈。在訪問被攔截的方法或字段時,攔截器鏈中的攔截器就會按其之前定義的順序被調用。
1.2. 攔截器的實現原理:
大部分時候,攔截器方法都是通過代理的方式來調用的。Struts 2的攔截器實現相對簡單。當請求到達Struts 2的ServletDispatcher時,Struts 2會查找配置文件,并根據其配置實例化相對的攔截器對象,然后串成一個列表(list),最后一個一個地調用列表中的攔截器。如下圖:
2. 攔截器的配置
Struts 2已經為您提供豐富多樣的,功能齊全的攔截器實現。大家可以至struts2的jar包內的struts-default.xml查看關于默認的攔截器與攔截器鏈的配置。
Struts2(XWork)提供的攔截器的功能說明:
攔截器
|
名字
|
說明
|
Alias Interceptor
|
alias
|
在不同請求之間將請求參數在不同名字件轉換,請求內容不變
|
Chaining Interceptor
|
chain
|
讓前一個Action的屬性可以被后一個Action訪問,現在和chain類型的result(<result type=”chain”>)結合使用。
|
Checkbox Interceptor
|
checkbox
|
添加了checkbox自動處理代碼,將沒有選中的checkbox的內容設定為false,而html默認情況下不提交沒有選中的checkbox。
|
Cookies Interceptor
|
cookies
|
使用配置的name,value來是指cookies
|
Conversion Error Interceptor
|
conversionError
|
將錯誤從ActionContext中添加到Action的屬性字段中。
|
Create Session Interceptor
|
createSession
|
自動的創建HttpSession,用來為需要使用到HttpSession的攔截器服務。
|
Debugging Interceptor
|
debugging
|
提供不同的調試用的頁面來展現內部的數據狀況。
|
Execute and Wait Interceptor
|
execAndWait
|
在后臺執行Action,同時將用戶帶到一個中間的等待頁面。
|
Exception Interceptor
|
exception
|
將異常定位到一個畫面
|
File Upload Interceptor
|
fileUpload
|
提供文件上傳功能
|
I18n Interceptor
|
i18n
|
記錄用戶選擇的locale
|
Logger Interceptor
|
logger
|
輸出Action的名字
|
Message Store Interceptor
|
store
|
存儲或者訪問實現ValidationAware接口的Action類出現的消息,錯誤,字段錯誤等。
|
Model Driven Interceptor
|
model-driven
|
如果一個類實現了ModelDriven,將getModel得到的結果放在Value Stack中。
|
Scoped Model Driven
|
scoped-model-driven
|
如果一個Action實現了ScopedModelDriven,則這個攔截器會從相應的Scope中取出model調用Action的setModel方法將其放入Action內部。
|
Parameters Interceptor
|
params
|
將請求中的參數設置到Action中去。
|
Prepare Interceptor
|
prepare
|
如果Acton實現了Preparable,則該攔截器調用Action類的prepare方法。
|
Scope Interceptor
|
scope
|
將Action狀態存入session和application的簡單方法。
|
Servlet Config Interceptor
|
servletConfig
|
提供訪問HttpServletRequest和HttpServletResponse的方法,以Map的方式訪問。
|
Static Parameters Interceptor
|
staticParams
|
從struts.xml文件中將<action>中的<param>中的內容設置到對應的Action中。
|
Roles Interceptor
|
roles
|
確定用戶是否具有JAAS指定的Role,否則不予執行。
|
Timer Interceptor
|
timer
|
輸出Action執行的時間
|
Token Interceptor
|
token
|
通過Token來避免雙擊
|
Token Session Interceptor
|
tokenSession
|
和Token Interceptor一樣,不過雙擊的時候把請求的數據存儲在Session中
|
Validation Interceptor
|
validation
|
使用action-validation.xml文件中定義的內容校驗提交的數據。
|
Workflow Interceptor
|
workflow
|
調用Action的validate方法,一旦有錯誤返回,重新定位到INPUT畫面
|
Parameter Filter Interceptor
|
N/A
|
從參數列表中刪除不必要的參數
|
Profiling Interceptor
|
profiling
|
通過參數激活profile
|
在struts.xml文件中定義攔截器,攔截器棧:
<package name="my" extends="struts-default" namespace="/manage">
<interceptors>
<!-- 定義攔截器 -->
<interceptor name="攔截器名" class="攔截器實現類"/>
<!-- 定義攔截器棧 -->
<interceptor-stack name="攔截器棧名">
<interceptor-ref name="攔截器一"/>
<interceptor-ref name="攔截器二"/>
</interceptor-stack>
</interceptors>
......
</package>
|
3. 使用攔截器
一旦定義了攔截器和攔截器棧后,就可以使用這個攔截器或攔截器棧來攔截Action了。攔截器的攔截行為將會在Action的exceute方法執行之前被執行。
<action name="userOpt" class="org.qiujy.web.struts2.action.UserAction">
<result name="success">/success.jsp</result>
<result name="error">/error.jsp</result>
<!-- 使用攔截器,一般配置在result之后, -->
<!-- 引用系統默認的攔截器 -->
<interceptor-ref name="defaultStack"/>
<interceptor-ref name="攔截器名或攔截器棧名"/>
</action>
|
此處需要注意的是,如果為Action指定了一個攔截器,則系統默認的攔截器棧將會失去作用。為了繼續使用默認攔截器,所以上面配置文件中手動引入了默認攔截器。
4. 自定義攔截器
作為“框架(framework)”,可擴展性是不可或缺的。雖然,Struts 2為我們提供如此豐富的攔截器實現,但是這并不意味我們失去創建自定義攔截器的能力,恰恰相反,在Struts 2自定義攔截器是相當容易的一件事。
4.1. 實現攔截器類:
所有的Struts 2的攔截器都直接或間接實現接口com.opensymphony.xwork2.interceptor.Interceptor。該接口提供了三個方法:
1) void init(); 在該攔截器被初始化之后,在該攔截器執行攔截之前,系統回調該方法。對于每個攔截器而言,此方法只執行一次。
2) void destroy();該方法跟init()方法對應。在攔截器實例被銷毀之前,系統將回調該方法。
3) String intercept(ActionInvocation invocation) throws Exception; 該方法是用戶需要實現的攔截動作。該方法會返回一個字符串作為邏輯視圖。
除此之外,繼承類com.opensymphony.xwork2.interceptor.AbstractInterceptor是更簡單的一種實現攔截器類的方式,因為此類提供了init()和destroy()方法的空實現,這樣我們只需要實現intercept方法。
4.2. 使用自定義攔截器:
兩個步驟:
l 通過<interceptor …>元素來定義攔截器。
l 通過<interceptor-ref …>元素來使用攔截器。
5. 自定義攔截器示例
5.1. 問題描述:
使用自定義攔截器來完成用戶權限的控制:當瀏覽者需要請求執行某個操作時,應用需要先檢查瀏覽者是否登錄,以及是否有足夠的權限來執行該操作。
5.2. 實現權限控制攔截器類:
AuthorizationInterceptor.java
package org.qiujy.common;
import java.util.Map;
import com.opensymphony.xwork2.Action;
import com.opensymphony.xwork2.ActionInvocation;
import com.opensymphony.xwork2.interceptor.AbstractInterceptor;
/**
*權限檢查攔截器
*
*@authorqiujy
*@version1.0
*/
publicclass AuthorizationInterceptor extends AbstractInterceptor {
/*
* 攔截Action處理的攔截方法
*
*/
public String intercept(ActionInvocation invocation) throws Exception {
Map session = invocation.getInvocationContext().getSession();
String userName = (String) session.get("userName");
if (null != userName && userName.equals("test")) {
System.out.println("攔截器:合法用戶登錄---");
return invocation.invoke();
} else {
System.out.println("攔截器:用戶未登錄---");
return Action.LOGIN;
}
}
}
|
5.3. 配置權限控制攔截器:
struts.xml:
<!DOCTYPE struts PUBLIC
"-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"
"http://struts.apache.org/dtds/struts-2.0.dtd">
<struts>
<package name="my" extends="struts-default">
<interceptors>
<!-- 定義權限控制攔截器 -->
<interceptor name="authority" class="org.qiujy.common.AuthorizationInterceptor"/>
</interceptors>
<!-- 定義全局處理結果 -->
<global-results>
<!-- 邏輯名為login的結果,映射到/login.jsp頁面 -->
<result name="login">/login.jsp</result>
</global-results>
<action name="listall" class="org.qiujy.web.struts2.action.UserAction" method="listAllUser">
<result name="success">/listall.jsp</result>
<!-- 使用攔截器 -->
<interceptor-ref name="defaultStack"/>
<interceptor-ref name="authority"/>
</action>
<action name="userOpt" class="org.qiujy.web.struts2.action.UserAction">
<result name="success">/success.jsp</result>
</action>
</package>
</struts>
|
其它頁面見源代碼。
5.4. 運行調試:
在瀏覽器地址欄直接輸入http://localhost:8080/AuthorityInterceptorDemo/listall.action來訪問,此動作配置了權限攔截器,所有被轉到登錄頁面。
登錄后:
再訪問http://localhost:8080/AuthorityInterceptorDemo/listall.action這個鏈接:



如果為了簡化struts.xml文件的配置,避免在每個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="my" extends="struts-default">
<interceptors>
<!-- 定義權限控制攔截器 -->
<interceptor name="authority"
class="org.qiujy.common.AuthorizationInterceptor" />
<!-- 定義一個包含權限控制的攔截器棧 -->
<interceptor-stack name="mydefault">
<interceptor-ref name="defaultStack" />
<interceptor-ref name="authority" />
</interceptor-stack>
</interceptors>
<!-- 定義默認攔截器 -->
<default-interceptor-ref name="mydefault" />
<!-- 定義全局處理結果 -->
<global-results>
<!-- 邏輯名為login的結果,映射到/login.jsp頁面 -->
<result name="login">/login.jsp</result>
</global-results>
<action name="listall"
class="org.qiujy.web.struts2.action.UserAction"
method="listAllUser">
<result name="success">/listall.jsp</result>
</action>
</package>
<package name="font" extends="struts-default">
<action name="userOpt" class="org.qiujy.web.struts2.action.UserAction">
<result name="success">/success.jsp</result>
</action>
</package>
</struts>
|
一旦在某個包下定義了默認攔截器棧,在該包下的所有action都會使用此攔截器棧。對于那些不想使用些攔截器棧的action,則應該將它放置在其它的包下。
posted on 2008-06-16 10:48
henry1451 閱讀(523)
評論(0) 編輯 收藏 所屬分類:
開源技術