8 Struts 2攔截器
8.1 理解攔截器
攔截器是Struts 2的核心,Struts 2的大部分功能都是由攔截器實現的。
在執行Action的execute方法之前,Struts 2會首先執行在struts.xml中引用的攔截器,在執行完所有引用的攔截器intercept方法後,會執行Action的execute方法。
8.1.1 攔截器的實現原理
當請求Action時,Struts 2會查找配置文件,並根據其配置實例化相對的攔截器對象,然後串成一個列表,最後一個一個的調用列表中的攔截器。
ServletDispatcher初始化一個ActionProxy實例,並調用execute方法→攔截器首先攔截用戶請求,然後交給Action處理→Action處理完畢,返回給用戶一個邏輯視圖
類似此功能的類:
TokenInterceptor
TokenSessionStoreInterceptor
DefaultWorkflowInterceptor
ValidationInterceptor
8.1.2 實現一個簡單攔截器
用戶自定義攔截器,三步:
1、自定義攔截器類(必須實現Interceptor接口或繼承AbstractInterceptor抽象類)
/** * 用戶自定義的攔截器類必須實行interceptor接口或繼承已實現了interceptor接口的抽象類AbstractInterceptor * 推薦使用抽象類AbstractInterceptor */ publicclass HelloInterceptor extends AbstractInterceptor{ ** * intercept方法:實現攔截器動作,參數ActionInvocation是被攔截Action的一個引用, * 可以調用該參數的invoke()方法,將控制器傳給下一個攔截器或Action的execute方法。 */ @Override public String intercept(ActionInvocation actionInvocation) throws Exception { System.out.println("攔截器開始運行。。。。"); String result = actionInvocation.invoke(); System.out.println("!攔截器結束了。。。。"); return result; }} |
2、在struts.xml中定義自定義的攔截器
在<interceptor>中定義攔截器
3、在struts.xml的<action>中使用攔截器
在<interceptor-ref>中使用攔截器
<packagename="helloInterceptor"extends="struts-default"> <!-- interceptor標記:用來定義一個具體的攔截器 --> <interceptors> <interceptor name="helloInterceptor" class="com.inter.HelloInterceptor"></interceptor> </interceptors> <!-- 攔截器使用:在一個具體的Action中,interceptor-ref標記就是使用已在interceptor標記中定義好的攔截器 --> <actionname="helloAction"class="com.action.HelloAction"> <resultname="success">/success.jsp</result> <resultname="input">/reg.jsp</result> <!--攔截器使用 --> <interceptor-refname="defaultStack"></interceptor-ref> <interceptor-refname="helloInterceptor"> </interceptor-ref> </action> </package> |
8.2 攔截器配置初步
8.2.1 struts-default.xml中攔截器的定義:
<interceptors> <interceptorname="conversionError"class="org.apache.struts2.interceptor.StrutsConversionErrorInterceptor"/> <interceptorname="exception"class="com.opensymphony.xwork2.interceptor.ExceptionMappingInterceptor"/> <interceptorname="params"class="com.opensymphony.xwork2.interceptor.ParametersInterceptor"/> <interceptorname="actionMappingParams"class="org.apache.struts2.interceptor.ActionMappingParametersInteceptor"/> <interceptorname="prepare"class="com.opensymphony.xwork2.interceptor.PrepareInterceptor"/> <interceptorname="checkbox"class="org.apache.struts2.interceptor.CheckboxInterceptor"/> <!-- Basic stack --> <interceptor-stackname="basicStack"> <interceptor-refname="exception"/> <interceptor-refname="servletConfig"/> <interceptor-refname="prepare"/> <interceptor-refname="checkbox"/> <interceptor-refname="multiselect"/> <interceptor-refname="actionMappingParams"/> <interceptor-refname="params"> <paramname="excludeParams">dojo\..*,^struts\..*</param> </interceptor-ref> <interceptor-refname="conversionError"/> </interceptor-stack> </interceptors> |
8.2.2 使用攔截器
只需在struts.xml的<action>中添加<interceptor-ref>標記中配置已定義好的攔截器。
<actionname="helloAction"class="com.action.HelloAction"> <interceptor-refname="defaultStack"></interceptor-ref> <interceptor-refname="helloInterceptor"></interceptor-ref> </action> |
當用戶使用了一個自定義的攔截器後,系統默認的攔截器defaultStack就會失效。所以必須添加上默認攔截器的配置代碼:
<interceptor-refname="defaultStack"></interceptor-ref>
8.2.3 使用攔截器的過濾方法特性
如何實現對Action的部分方法進行攔截?
Struts 2爲了實現方法過濾功能,定義了MethodFilterInterceptor類,該類繼承了AbstractInterceptor類。該類重寫了AbstractInterceptor類的intercept方法,提供了一個doIntercept的抽象方法,自定義攔截邏輯。
(1)在Action中進行配置:
publicclass FilterHelloInterceptor extends MethodFilterInterceptor{ @Override protected String doIntercept(ActionInvocation arg0) throws Exception { System.out.println("邏輯實現過程是一樣的,只是方法名不同而已。"); String res = arg0.invoke(); return res;} * MethodFilterInterceptor類中兩個重要的方法可用於方法的過濾: * setExcludeMethods(排除過濾)和setIncludeMethods(要過濾), * 衝突時,以setIncludeMethods爲準 * 這兩個方法靈活性不夠,所以可以在struts.xml中進行方法是否過濾的配置 @Override publicvoid setExcludeMethods(String excludeMethods) { super.setExcludeMethods(excludeMethods); } @Override publicvoid setIncludeMethods(String includeMethods) { super.setIncludeMethods(includeMethods); }} |
(2)struts.xml中配置
<packagename="filterHelloInterceptor"extends="struts-default"> <interceptors> <interceptorname="filterHelloInterceptor"class="com.inter.FilterHelloInterceptor"></interceptor> </interceptors> <actionname="sayHello"class="com.action.SayHelloAction"> <result>success.jsp</result> <!--name="excludeMethods"表示要添加排除過濾的方法,當前配置要排除的攔截方法是execute--> <interceptor-refname="filterHelloInterceptor"> <paramname="excludeMethods">execute</param> </interceptor-ref> </action> </package> |
8.3 Struts 2內建的攔截器
8.4 使用攔截器進行權限控制
檢測用戶是否登錄,通常是跟蹤用戶的session來完成的。通過ActionContext訪問session中的屬性。
攔截器代碼:
publicclass CheckInterceptor extends AbstractInterceptor{ /** * 用intercept方法對session中是否存在admin用戶作了驗證,若用戶名爲admin,則 爲合法用戶,可跳轉到success.jsp頁面,否則留在登錄界面,並給出錯誤提示。 */ @Override public String intercept(ActionInvocation arg0) throws Exception { ActionContext ac = arg0.getInvocationContext(); Map<?, ?> sessionMap = ac.getSession(); String user = (String) sessionMap.get("name");//從sessionMap中得到用戶實例 if(user!=null&&user.equals("admin")){ return arg0.invoke(); } ac.put("tip","請先登錄!"); return Action.LOGIN; }} |
ActionContext中的tip在JSP頁面中取出:${requestScope.tip }