Struts2學習——攔截器(interceptor)學習
阿新 • • 發佈:2018-12-09
-
攔截器(interceptor)是struts2框架的又一主要功能,他是基於過濾器(Filter)來開發的,主要功能就是對使用者的請求進行包裝,處理等等。
-
例如,前面學習的Action中獲取引數的幾種方式,都是在請求到達Action之前,在攔截器中進行獲取並封裝的,我們在Action類中建立屬性,只不過是給獲取的引數建立一個容器,好讓前面的攔截器可以將引數封裝進去。
-
Struts2框架自帶了一堆攔截器(20個左右)
- 這是Struts2預設的攔截器棧,也就是請求到達action預設要經過這些攔截器。可以看到其中有一個叫做
- <interceptor-ref name="modelDriven"/>
- 的攔截器,他的功能就是實現模型驅動封裝引數。
<interceptor-stack name="defaultStack"> <interceptor-ref name="exception"/> <interceptor-ref name="alias"/> <interceptor-ref name="servletConfig"/> <interceptor-ref name="i18n"/> <interceptor-ref name="prepare"/> <interceptor-ref name="chain"/> <interceptor-ref name="scopedModelDriven"/> <interceptor-ref name="modelDriven"/> <interceptor-ref name="fileUpload"/> <interceptor-ref name="checkbox"/> <interceptor-ref name="datetime"/> <interceptor-ref name="multiselect"/> <interceptor-ref name="staticParams"/> <interceptor-ref name="actionMappingParams"/> <interceptor-ref name="params"/> <interceptor-ref name="conversionError"/> <interceptor-ref name="validation"> <param name="excludeMethods">input,back,cancel,browse</param> </interceptor-ref> <interceptor-ref name="workflow"> <param name="excludeMethods">input,back,cancel,browse</param> </interceptor-ref> <interceptor-ref name="debugging"/> </interceptor-stack>
我們知道有的系統(網站)、會要求使用者必須登入,否則就無法使用網站中的各種功能,這就可以使用攔截器來實現,想要使用攔截器實現,當然要回建立並配置攔截器,接下來就學習了攔截器的基本用法:
-
1. 如何建立攔截器interceptor
建立攔截器又有三種方式:
- 方式一:實現Interceptor介面(最原始的方式)
// 介面中有三個方法需要實現,分別是建立時執行的方式、銷燬時執行的方法,和攔截器具體行為 // 這裡介紹一下攔截器的生命週期:隨專案工程部署而建立(開啟伺服器)、隨專案關閉而銷燬 public class MyInterceptor1 implements Interceptor{ @Override public void destroy() { } @Override public void init() { } @Override // intercept方法,引數顧名思義:Action呼叫,用於執行action類的物件 public String intercept(ActionInvocation invocation) throws Exception { /* * 放行之前書寫在action執行之前的操作 */ // 放行 String str =i nvocation.invoke(); /* * 放行之後書寫在action執行之後的操作 */ return str; // 如果不想放行(不執行後續攔截器及Action類),可以直接返回一個結果字元創,如error // return "error"; // 當然前面的放行程式碼可以刪掉,這樣他會直接去到配置的中 // 查詢name為error的result元素,並執行相應的跳轉操作 } }
- 方式二:繼承AbstractInterceptor 類
// AbstractInterceptor類也是實現的Interceptor介面,他只是方便開發者書寫程式碼, // 因為init方法與destroy方法基本用不到,所以他就簡化了需要實現的方法。 public class MyInterceptor1 extends AbstractInterceptor{ @Override public String intercept(ActionInvocation arg0) throws Exception { return null; } }
- 方式三:繼承MethodFilterInterceptor 類
// MethodFilterInterceptor類可以說是方法過濾攔截器。 // 他的功能就是:定製攔截器攔截的方法——攔截哪些方法、不攔截哪些方法 // 具體程式碼與其他幾種方式相同 public class MyInterceptor1 extends MethodFilterInterceptor{ @Override protected String doIntercept(ActionInvocation arg0) throws Exception { return null; } }
-
2. 如何使用(配置)攔截器
- 寫好了攔截器後,當然要使其生效,所以需要對攔截器進行具體配置,有優秀基礎的人,攔截器配置的步驟可以參照struts-default.xml中的配置來寫。
攔截器配置步驟:
- 1. 註冊攔截器
<!-- 攔截器主元素:位置:package元素裡面,action元素前面 --> <interceptors> <!-- interceptor元素:用於註冊攔截器 name屬性:為該攔截器起個名稱; class屬性:填寫該攔截器類的全包名 --> <interceptor name="login" class="com.huhu.web.interceptor.MyInterceptor"></interceptor> </interceptors>
- 2. 建立攔截器棧
<!-- 該元素建立攔截器棧,放在interceptors元素裡面,interceptor元素後面。name屬性,為棧起個名稱--> <interceptor-stack name="loginStack"> <!-- 將自己書寫的攔截器棧引入進來,並引入struts2預設的攔截器 --> <interceptor-ref name="login"></interceptor-ref> <interceptor-ref name="defaultStack"></interceptor-ref> </interceptor-stack>
- 3. 指定攔截器工作範圍
<!-- 直接在package元素裡配置此元素,意思是該package下的所有action都要走name為loginStack的攔截 器棧 --> <default-interceptor-ref name="loginStack"></default-interceptor-ref> <!-- 也可以指定某個action元素適用的攔截器棧(不常用) 將interceptor-ref元素配置在action裡面,即指定該action適用的攔截器棧 --> <action> <interceptor-ref name="loginStack"></interceptor-ref> </action>
-
到這裡,技術點都學完了,之後就是適用這些知識實現效果:
-
訪問功能時,未登入,則跳轉到登入頁面。
詳細實現:這裡就簡單的將程式碼貼出來。
- 攔截器具體程式碼:
public class LoginInterceptor extends MethodFilterInterceptor{ @Override protected String doIntercept(ActionInvocation invocation) throws Exception { // 獲取session域,獲取user Object user = ActionContext.getContext().getSession().get("user"); // 判斷使用者是否登入(user是否存在) if (user == null) { // 未登入,跳轉到登入頁面 return "toLogin"; } // 登入放行 return invocation.invoke(); } }
- 配置檔案詳細程式碼:
<package name="sh" namespace="/" extends="struts-default"> <!-- 配置程式設計師自定義攔截器,放在package元素的最前面 --> <interceptors> <!-- 註冊攔截器 --> <interceptor name="login" class="com.huhu.web.interceptor.LoginInterceptor"></interceptor> <interceptor-stack name="loginStack"> <!-- 將註冊的攔截器新增到自定義攔截器棧 --> <interceptor-ref name="login"> <!-- 配置不執行此攔截器棧的方法 --> <param name="excludeMethods">login</param> </interceptor-ref> <!-- 引入struts2預設攔截器棧 --> <interceptor-ref name="defaultStack"></interceptor-ref> </interceptor-stack> </interceptors> <!-- 設定package預設攔截器棧 --> <default-interceptor-ref name="loginStack"></default-interceptor-ref> <!-- 配置全域性結果集,整個工程都可以使用的結果集 ,放在全域性異常處理之前--> <global-results> <result name="toLogin" type="redirect">/login.jsp</result> </global-results> <action name="custAction_*" class="com.huhu.web.action.CustomerAction" method="{1}"> <result name="custlist" >/jsp/customer/list.jsp</result> <result name="success" type="redirectAction"> <param name="actionName">custAction_findCust</param> <param name="namespace">/customer</param> </result> <!-- 配置可以動態呼叫的方法名,多個方法用,逗號隔開 --> <allowed-methods>findCust,add</allowed-methods> </action> <action name="userAction_*" class="com.huhu.web.action.UserAction" method="{1}"> <interceptor-ref name="loginStack"></interceptor-ref> <result name="login" type="redirect">/index.jsp</result> <result name="error" type="dispatcher">/login.jsp</result> <!-- 不知道為啥,以轉發的方式到頁面,頁面載入不到資源,原因:資源路徑前沒加工程名 --> <!-- <result name="error" >/login.jsp</result> --> <allowed-methods>login</allowed-methods> </action> </package>
這也可以說是已經實現了登入校驗的功能(校驗使用者是否登入)
拓展:
-
1. 攔截器無法攔截頁面的顯示,只能攔截action中的元素,所以想要實現攔截頁面的功能需要使用其他的技術。或者,每個頁面的顯示都是使用action的某個方法跳轉到的,則可以用攔截器攔截這些方法,來起到攔截頁面顯示的作用,不過這種方式可能不太常用。
-
2. 如果頁面使用的是frame框架佈局的頁面,未登入時,跳轉到登入頁面可能只是框架中的某一部分跳轉,如:
-
如果想讓跳轉到的登入頁只顯示登入頁資訊,可以使用js的一段簡單程式碼解決:
- 注意:此段程式碼實在想要顯示的頁面的檔案中書寫的,如:我的登入頁面檔名為login.jsp,則在該檔案中書寫
<script type="text/javascript">
window.onload=function(){
if(window.parent != window){
window.parent.location.href="${pageContext.request.contextPath}/login.jsp";
}
};
</script>
-
書寫一個頁面載入完畢事件,作用是,頁面載入完畢後,判斷當前頁面的父視窗是不是瀏覽器的主視窗,如果不是,則將父視窗重新跳轉到當前頁面。