一、struts2中的攔截器(框架功能核心)
1、過濾器VS攔截器
過濾器VS攔截器功能是一回事。過濾器是Servlet規範中的技術,可以對請求和響應進行過濾。
攔截器是Struts2框架中的技術,實現AOP(面向切面)的編程思想,是可插拔的, 可以對訪問某個Action 方法之前或之後實施攔截。
攔截器棧(Interceptor Stack): 將攔截器按一定的順序聯結成一條鏈. 在訪問被攔截的方法時, Struts2攔截器鏈中的攔截器就會按其之前定義的順序被依次調用
Struts2執行原理- 底層分析
2、自定義攔截器
struts2定義了一個攔截器接口Interceptor接口。
Interceptor接口裡面有三個抽象方法
•init: 該方法將在攔截器被創建後立即被調用, 它在攔截器的生命週期內只被調用一次. 可以在該方法中對相關資源進行必要的初始化
•interecept: 每攔截一個動作請求, 該方法就會被調用一次.
•destroy: 該方法將在攔截器被銷毀之前被調用, 它在攔截器的生命週期內也只被調用一次.
Struts 會依次調用程序員為某個Action 而註冊的每一個攔截器的interecept 方法.每次調用interecept 方法時, Struts 會傳遞一個ActionInvocation 接口的實例.
ActionInvocation: 代表一個給定動作的執行狀態, 攔截器可以從該類的對象裡獲得與該動作相關聯的Action 對象和Result 對象. 在完成攔截器自己的任務之後, 攔截器將調用ActionInvocation 對象的invoke 方法前進到Action 處理流程的下一個環節.
還可以調用ActionInvocation 對象的addPreResultListener 方法給ActionInvocation 對象“掛” 上一個或多個PreResultListener 監聽器. 該監聽器對象可以在動作執行完畢之後, 開始執行動作結果之前做些事情
自定義攔截器步驟:
a、編寫一個類,實現com.opensymphony.xwork2.interceptor.Interceptor接口,或者繼承
com.opensymphony.xwork2.interceptor.AbstractInterceptor類。 (適配器模式),一般都選擇繼承AbstractInterceptor(攔截器會駐留內存)。因為AbstractInterceptor 類實現了Interceptor 接口. 並為init, destroy 提供了一個空白的實現
編寫兩個攔截器InterceptorDemo1 ,和InterceptorDemo2
package com.itheima.interceptor;import com.opensymphony.xwork2.ActionInvocation;import com.opensymphony.xwork2.interceptor.AbstractInterceptor;public class InterceptorDemo1 extends AbstractInterceptor { //動作的每次訪問都會調用該方法public String intercept(ActionInvocation invocation) throws Exception { System.out.println("攔截前Demo1"); String rtvalue = invocation.invoke();//放行,這里為什麼返回string?因為最終的結果返回的Action的Result,而action的結果是string類型System.out.println("攔截後Demo1"); return rtvalue; }}package com.itheima.interceptor;import com.opensymphony.xwork2.ActionInvocation;import com.opensymphony.xwork2.interceptor.AbstractInterceptor;import com.opensymphony.xwork2.interceptor.PreResultListener;public class InterceptorDemo2 extends AbstractInterceptor { //動作的每次訪問都會調用該方法public String intercept(ActionInvocation invocation) throws Exception {// invocation.addPreResultListener(new PreResultListener() {// // public void beforeResult(ActionInvocation invocation, String resultCode) {// System.out.println("結果顯示前");// }// }); System.out.println("攔截前Demo2"); String rtvalue = invocation.invoke();//放行System.out.println("攔截後Demo2"); return rtvalue; }}b、需要在struts.xml中進行定義,定義攔截器,先定義在使用。
<package name="p1" extends="struts-default"> <!-- 定義攔截器:只對當前包有效--> <interceptors> <interceptor name="interceprotDemo1"></interceptor> <interceptor name="interceprotDemo2"></interceptor> </interceptors></package>
c、在動作配置中就可以使用了
<action name="action1" method="execute"> <!-- 使用定義的攔截器。如過沒有指定任何的攔截器,默認使用default-stack棧中的所有攔截器; 一旦指定了任何一個攔截器,默認的就無效了--> <interceptor-ref name="interceprotDemo1"></interceptor-ref> <interceptor-ref name="interceprotDemo2"></interceptor-ref> <result>/success.jsp</result></action>
實現動作類Demo1Action
package com.itheima.action;import com.opensymphony.xwork2.ActionSupport;public class Demo1Action extends ActionSupport { @Override public String execute() throws Exception { System.out.println("execute執行了"); return SUCCESS; }}運行結果
因為struts2中如文件上傳,數據驗證,封裝請求參數到action等功能都是由系統默認的defaultStack中的攔截器實現的,所以我們定義的攔截器需要引用系統默認的defaultStack,這樣應用才可以使用struts2框架提供的眾多功能。
如過沒有指定任何的攔截器,默認使用default-stack棧中的所有攔截器;一旦指定了任何一個攔截器,默認的就無效了除了要使用自定義的攔截器之外,還要使用defaultStack,可以這麼辦
方法一: (自己使用),只需在action中配置自定義的和defaultStack默認的就可以了。
方法二: (大家都用的時候),如果希望包下的所有action都使用自定義的攔截器, 要使用攔截器棧interceptor-stack,定義一個interceptor-stack,然後在action中可以通過<default-interceptor-ref name=“mydefaultStack”/>把攔截器定義為默認攔截器,mydefaultStack名字可以自己取。
<interceptors> <interceptor name="interceprotDemo1"></interceptor> <interceptor name="interceprotDemo2"></interceptor> <interceptor-stack name="mydefaultStack"> <interceptor-ref name="defaultStack"></interceptor-ref> <interceptor-ref name="interceprotDemo1"></interceptor-ref> <interceptor-ref name="interceprotDemo2"></interceptor-ref> </interceptor-stack></interceptors><action name="action3" method="login"> <interceptor-ref name="mydefaultStack"></interceptor-ref> <result>/success.jsp</result></action>
3、Struts2 自帶的攔截器
案例1:檢查用戶是否登錄
1、 編寫頁面login.jsp
<body> <form action="${pageContext.request.contextPath}/login.action" method="post"> <input type="text" name="username"/><br/> <input type="text" name="password"/><br/> <input type="submit" value="登錄"/> </form> </body>2、編寫登錄校驗的攔截器LoginCheckInterceptor 類
package com.itheima.interceptor;import javax.servlet.http.HttpSession;import org.apache.struts2.ServletActionContext;import com.opensymphony.xwork2.ActionInvocation;import com.opensymphony.xwork2.interceptor.AbstractInterceptor;public class LoginCheckInterceptor extends AbstractInterceptor { public String intercept(ActionInvocation invocation) throws Exception { HttpSession session = ServletActionContext.getRequest().getSession();//通過ServletActionContext對象獲得session對象Object user = session.getAttribute("user"); if(user==null){ //沒有登錄return "login";//返回到某個邏輯視圖} return invocation.invoke();//放行}}3、編寫配置文件struts.xml
<package name="p2" extends="struts-default"> <interceptors> <interceptor name="loginCheckInterceptor"></interceptor> <interceptor-stack name="mydefaultStack"> <interceptor-ref name="defaultStack"></interceptor-ref> <interceptor-ref name="loginCheckInterceptor"></interceptor-ref> </interceptor-stack> </interceptors> <action name="login" method="login"> <result>/login.jsp</result> </action> </package>
4、編寫動作類CustomerAction
package com.itheima.action;import org.apache.struts2.ServletActionContext;import com.opensymphony.xwork2.ActionSupport;public class CustomerAction extends ActionSupport { public String login(){ System.out.println("登錄"); ServletActionContext.getRequest().getSession().setAttribute("user", "ppp"); return SUCCESS; }}案例2:監測動作方法的執行效率
編寫時間監測過濾器TimerInterceptor
package com.itheima.interceptor;import com.opensymphony.xwork2.ActionInvocation;import com.opensymphony.xwork2.interceptor.AbstractInterceptor;public class TimerInterceptor extends AbstractInterceptor { public String intercept(ActionInvocation invocation) throws Exception { long time = System.nanoTime(); String rtvalue = invocation.invoke(); System.out.println(rtvalue+"執行耗時:"+(System.nanoTime()-time)+"納秒"); return rtvalue; }}編寫配置文件
<package name="p2" extends="struts-default"> <interceptors> <interceptor name="loginCheckInterceptor"></interceptor> <interceptor name="timerInterceptor"></interceptor> <interceptor-stack name="mydefaultStack"> <interceptor-ref name="defaultStack"></interceptor-ref> <interceptor-ref name="loginCheckInterceptor"></interceptor-ref> <interceptor-ref name="timerInterceptor"></interceptor-ref> </interceptor-stack> </interceptors> <result name="login">/login.jsp</result> </action> </package>
從上面可以看出,在一個action 中可以配置多個過濾器。
4、自定義攔截器:能夠指定攔截的方法或不攔截的方法
能夠指定攔截的方法或不攔截的方法,編寫過濾器時,可以實現類MethodFilterInterceptor,裡面有兩個字段,通過注入參數就可以指定那些不攔截,兩個參數只要用一個即可,當攔截較少是,可以用includeMethods ,當攔截較多是,可以用排除的方法excludeMethods 。
excludeMethods = Collections.emptySet();//排除那些
includeMethods = Collections.emptySet();//包括那些
案例:再續登錄校驗的例子。
1、編寫過濾器LoginCheckInterceptor
package com.itheima.interceptor;import javax.servlet.http.HttpSession;import org.apache.struts2.ServletActionContext;import com.opensymphony.xwork2.ActionInvocation;import com.opensymphony.xwork2.interceptor.AbstractInterceptor;import com.opensymphony.xwork2.interceptor.MethodFilterInterceptor;public class LoginCheckInterceptor extends MethodFilterInterceptor { protected String doIntercept(ActionInvocation invocation) throws Exception { HttpSession session = ServletActionContext.getRequest().getSession(); Object user = session.getAttribute("user"); if(user==null){ //沒有登錄return "login";//返回到某個邏輯視圖} return invocation.invoke();//放行}}2、編寫配置文件
3、編寫動作類CustomerAction
package com.itheima.action;import org.apache.struts2.ServletActionContext;import com.opensymphony.xwork2.ActionSupport;public class CustomerAction extends ActionSupport { public String add(){ System.out.println("調用add的service方法"); return SUCCESS; } public String edit(){ System.out.println("調用edit的service方法"); return SUCCESS; } public String login(){ System.out.println("登錄"); ServletActionContext.getRequest().getSession().setAttribute("user", "ppp"); return SUCCESS; }} 4、編寫頁面
addCustomer.jsp
<body> 添加客戶</body>
editCustomer.jsp
<body> 修改客戶</body>
login.jsp
<body> <form action="${pageContext.request.contextPath}/login.action" method="post"> <input type="text" name="username"/><br/> <input type="text" name="password"/><br/> <input type="submit" value="登錄"/> </form> </body>success.jsp
<body> oyeah </body>
以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持武林網。