1.struts2能完成數據的設置,數據的封裝,數據的類型轉換,數據的校驗等等。struts2是如何來完成這些功能的?struts2的所有功能都是由攔截器來完成的。
2.攔截器是struts2的核心。攔截器是一個類似於過濾器的類。在執行action的處理方法前會 先執行攔截器,然后再執行action的處理方法,然后再執行攔截器,再響應。
3. struts2的所有功能都是由攔截器來實現的,而攔截器在struts2中時可以自由配置和自由裝配的。所以struts2的所有功能也都是可插拔的。並且struts2中的攔截器是可以自定義的,所以如果struts2沒有提供項目所需的功能時,可以通過自定義攔截器來實現。
4. struts2的攔截器有哪些,分別有什么功能:
- alias : 對於HTTP請求包含的參數設置別名
- autowiring : 將某些JavaBean實例自動綁定到其他Bean對應的屬性中。有點類似Spring的自動綁定,在Spring部分會詳細說明
- chain : 在Web項目開發中,以前使用Struts開發的時候經常碰到兩個Action互相傳遞參數或屬性的情況。該攔截器就是讓前一個Action的參數可以在現有Action中使用。
- conversionError : 從ActionContext中將轉化類型時候發生的錯誤添加到Action的值域錯誤中,在檢驗的時候經常被使用來顯示類型轉化的錯誤信息
- cookie : 從Struts2.0.7版本開始,可以把cookie注入Action中可設置的名字或值中
- createSession : 自動創建一個HTTP的 Session, 尤其是對需要HTTP的Session的攔截器特別有用。比如下面介紹的TokenInterceptor
- debugging : 用來對在視圖間傳遞的數據進行調試
- execAndWait : 不顯示執行Action, 在視圖上顯示給用戶的是一個正在等待的頁面,但是Action其實是在背后正在執行着。該攔截器尤其在對進度條進行開發的時候特別有用。
- exception : 將異常和Action返回的result相映射
- fileUpload : 支持文件上傳功能的攔截器
- i18n : 支持國際化的攔截器
- logger : 擁有日志功能的攔截器
- modelDriven : Action執行該攔截器的時候,它可以從一個scope范圍檢索和存儲model值,通過調用setModel方法去設置model的值
- params : 將HTTP請求中包含的參數值設置到Action中
- prepare : 假如Action繼承了Preparable接口,則會調用prepare方法
- staticParams : 對於在struts.xml文件中的Action中設置的參數設置到對應的Action中
- scope : 在session或者application范圍中設置Action的狀態
- servletConfig : 該攔截器提供訪問包括HttpServletRequest和HttpServletResponse對象的Map方法
- timer : 輸出Action的執行時間
- token : 避免重復提交的校驗攔截器
- tokenSession : 和token攔截器類似,但它還能存儲提交的數據到session里
- validation : 運行在action-validation.xml文件中定義的校驗規則。(數據校驗部分)
- workflow : 在Action中調用validate檢驗方法。如果Action有錯誤則返回到 input 視圖
- store : 執行校驗功能的時候,該攔截器提供存儲和檢索Action的所有錯誤和正確信息的功能
- checkbox : 視圖中如果有checkbox存在的情況,該攔截器自動將unchecked的checkbox當做一個參數(通常為false)記錄下來。這樣可以用一個隱藏的表單值來記錄所有未提交的checkbox,而且缺省unchecked的checkbox值是布爾類型的,如果視圖中checkbox的值設置的不是布爾類型,它就會被覆蓋成布爾類型的值
- profiling : 通過參數來激活或者不激活分析檢測功能,前提示Web項目是在開發模式下。(涉及到調試和性能檢驗時使用)
- roles : 進行權限配置的攔截器,如果登錄用戶擁有相應的權限才去執行某一特定的Action
5.struts2中攔截器定義的位置在struts-default.xml中
6.自定義攔截器步驟:
a) 編寫類,實現Interceptor接口
public class ActionExecuteTimeInterceptor implements Interceptor{ @Override public void destroy() { } @Override public void init() { } @Override public String intercept(ActionInvocation invocation) throws Exception { long start=System.currentTimeMillis(); //執行下一個攔截器 如果下面沒有攔截器則執行action的處理方法,並將結果返回 String result = invocation.invoke(); System.out.println("執行時間為:"+(System.currentTimeMillis()-start)); return result; } }
b) 在struts.xml中配置攔截器
<!-- 攔截器配置 --> <interceptors> <!-- 配置自定義攔截器 name 是唯一的 class 是自定義攔截器的完全限定名 --> <interceptor name="executeTime" class="cn.sxt.interceptor.ActionExecuteTimeInterceptor"></interceptor> </interceptors>
c) 在對應action中 引用自定義攔截器
<package name="default" extends="struts-default" namespace="/"> <!-- 攔截器配置 --> <interceptors> <!-- 配置自定義攔截器 name 是唯一的 class 是自定義攔截器的完全限定名 --> <interceptor name="executeTime" class="cn.sxt.interceptor.ActionExecuteTimeInterceptor"></interceptor> </interceptors> <action name="add" class="cn.sxt.action.UserAction" method="add"> <result>/success.jsp</result> <!-- 在action中引用自定義的攔截器 --> <interceptor-ref name="executeTime"></interceptor-ref> </action> </package>
7.自定義攔截器有兩種方式實現,一種實現Interceptor接口還可以繼承AbstractInterceptor類來實現:如:
public class HelloInterceptor extends AbstractInterceptor{ @Override public String intercept(ActionInvocation invocation) throws Exception { System.out.println("hello interceptor 被執行"); return invocation.invoke(); } }
8.如果引用了自定義攔截器,那么struts2的攔截器將不再起作用。如果需要使用struts2的攔截器需要手動引入。
<action name="add" class="cn.sxt.action.UserAction" method="add"> <result>/success.jsp</result> <!-- 在action中引用自定義的攔截器 --> <interceptor-ref name="executeTime"></interceptor-ref> <interceptor-ref name="helloInterceptor"></interceptor-ref> <interceptor-ref name="defaultStack"></interceptor-ref> </action>
9.當自定義攔截器比較多時,在action中引用攔截器將會變得比較麻煩,所以呢,struts2提供了攔截器棧。攔截器棧是用來引用已經定義好的攔截器的。一個攔截器棧可以包括多個攔截器,引用攔截器棧的方式和引用攔截器的方式一樣。
<!-- 攔截器配置 --> <interceptors> <!-- 配置自定義攔截器 name 是唯一的 class 是自定義攔截器的完全限定名 --> <interceptor name="helloInterceptor" class="cn.sxt.interceptor.HelloInterceptor"></interceptor> <interceptor name="executeTime" class="cn.sxt.interceptor.ActionExecuteTimeInterceptor"></interceptor> <!-- 定義攔截器棧 --> <interceptor-stack name="myStack"> <interceptor-ref name="executeTime"></interceptor-ref> <interceptor-ref name="helloInterceptor"></interceptor-ref> <interceptor-ref name="defaultStack"></interceptor-ref> </interceptor-stack> </interceptors> <action name="add" class="cn.sxt.action.UserAction" method="add"> <result>/success.jsp</result> <!-- 在action中引用自定義的攔截器 --> <interceptor-ref name="myStack"></interceptor-ref> </action>
10.在struts2如果沒有自定義攔截器時,action類會引用默認的攔截器棧。如果有自定義攔截器后,想自定義攔截器設置為默認攔截器應該如何操作?
在package中去定義一個default-interceptor-ref即可。
<!-- 設置默認攔截器 --> <default-interceptor-ref name="myStack"></default-interceptor-ref> <action name="add" class="cn.sxt.action.UserAction" method="add"> <result>/success.jsp</result> </action>
11.攔截器的使用:
登錄攔截器用來實現用戶登錄檢查:
public class LoginInterceptor extends AbstractInterceptor{ @Override public String intercept(ActionInvocation invocation) throws Exception { //判斷執行的Action是否login.action //如果不是 判斷用戶是否登錄 //如果登錄了 執行下一個攔截器,如果沒有登錄 去登錄 //獲取執行action的名稱 String actionName=invocation.getProxy().getActionName(); if("login".equals(actionName)){ return invocation.invoke(); } Object obj=ServletActionContext.getRequest().getSession().getAttribute("currentUser"); if(obj!=null){ return invocation.invoke(); } return Action.LOGIN; } }
配置
<struts> <package name="default" extends="struts-default" namespace="/"> <!-- 攔截器配置 --> <interceptors> <interceptor name="loginInterceptor" class="cn.sxt.interceptor.LoginInterceptor"></interceptor> <interceptor-stack name="myStack"> <interceptor-ref name="loginInterceptor"></interceptor-ref> <interceptor-ref name="defaultStack"></interceptor-ref> </interceptor-stack> </interceptors> <default-interceptor-ref name="myStack"></default-interceptor-ref> <!-- 定義全局結果集 --> <global-results> <result name="login">/login.jsp</result> </global-results> <action name="login" class="cn.sxt.action.UserAction" method="login"> <result>/success.jsp</result> </action> <action name="show" class="cn.sxt.action.UserAction" method="show"> <result>/show.jsp</result> </action> </package> </struts>
12.總結:
攔截器是單列的,所有action執行的都是同一個攔截器。所以在自定義攔截器時要注意線程安全的問題。攔截器只攔截action。
13.注意過濾器和攔截器區別
14. 方法攔截器
方法攔截器是比攔截器更加細粒度的攔截器,只攔截方法。通過配置方法攔截器可以有效提高系統性能。
/** * 自定義方法攔截器 * */ public class AddMethodInterceptor extends MethodFilterInterceptor{ @Override protected String doIntercept(ActionInvocation invocation) throws Exception { System.out.println("進入方法攔截器"); return invocation.invoke(); } }
配置
<!-- 配置方法攔截器 --> <interceptor name="addInterceptor" class="cn.sxt.interceptor.AddMethodInterceptor"> <!-- 配置哪些方法 需要被攔截 --> <param name="includeMethods">add</param> <!-- 排除哪些方法不被攔截 <param name="excludeMethods"></param> --> </interceptor>