1、Struts2攔截器概述:
(1)Struts2框架封裝中封裝了很多功能,這些功能其實都是封裝在Struts2的攔截器里面,Struts2里面有很多攔截器,每次不是這些攔截器都執行,每次只執行默認的攔截器。
(2)Struts2默認攔截器的位置:
(3)攔截器在Action對象創建之后,action的方法執行之前執行。
2、Struts2底層原理:
(1)原理一(AOP思想):
AOP:面向切面(方面)編程,不通過修改源代碼的方式來擴展功能。
在上面的登錄流程圖中,如果在登錄成功后要添加用戶的權限判斷功能,不需要修改源代碼。
(2)責任鏈模式(和過濾鏈模式思想相似):
過濾鏈模式:一個請求需要經過多個過濾器,而每個過濾器只有經過放行操作后才能進行下一步操作。
責任鏈模式:例如執行:添加、刪除、修改操作,先執行添加操作,添加操作執行結束之后執行刪除操作(類似於過濾鏈模式中的放行操作),執行刪除操作之后執行修改操作。
3、AOP思想和責任鏈模式在Struts2中的應用:
(1)攔截器在Action對象創建之后,action的方法執行之前執行(在Action方法執行之前執行默認攔截器,執行過程中使用AOP思想,在Action中沒有直接調用攔截器的方法,而是使用配置文件的方式進行操作)。
(2)如果攔截器執行過程中有多個攔截器則采用責任鏈模式進行,如果有三個攔截器,則先執行攔截器一,執行一之后做放行操作,然后執行攔截器二,做放行操作,最后執行攔截器三,放行后,執行Action方法。
4、過濾器和攔截器的區別:
(1)過濾器:過濾器理論上可以過濾任何內容,例如:圖片、html、jsp、servlet的路徑。
(2)攔截器:攔截器只能攔截Action。
5、servlet和action的區別:
(1)servlet:只在首次訪問的時候創建,只創建一次(單實例對象)
(2)action:每次訪問的時候創建,可以創建多次(多實例對象)
6、生命周期:
隨項目的啟動而創建,隨項目的關閉而銷毀。
7、攔截器的創建方法
(1)方法一:實現接口(需要實現三個方法,不推薦)
import com.opensymphony.xwork2.ActionInvocation; import com.opensymphony.xwork2.interceptor.Interceptor; public class InterceptorDemo implements Interceptor { @Override public void destroy() { } @Override public void init() { } @Override public String intercept(ActionInvocation actionInvocation) throws Exception { return null; } }
(2)方法二:繼承AbstractInterceptor類,因為該類已經實現了Interceptor接口,因此較為方便(幫我們實現了init和destory方法,就可以只實現intercept方法):
import com.opensymphony.xwork2.ActionInvocation; import com.opensymphony.xwork2.interceptor.AbstractInterceptor; public class InterceptorDemo1 extends AbstractInterceptor { @Override public String intercept(ActionInvocation actionInvocation) throws Exception { return null; } }
(3)方法三:
public class InterceptorDemo2 extends MethodFilterInterceptor { @Override protected String doIntercept(ActionInvocation actionInvocation) throws Exception { actionInvocation.invoke();//放行 return null; } }
調用invoke()之前的代碼叫做前處理,之后的代碼叫做后處理。要是不想放行只需要返回一個字符串即可(不調用invoke()方法)。這樣就不會執行后續的攔截器和Action,直接交給Result處理結果。
8、攔截器的配置
(1)先查看系統對攔截器的配置:
指明攔截器類:
<interceptors> <interceptor name="alias" class="com.opensymphony.xwork2.interceptor.AliasInterceptor"/> <interceptor name="autowiring" class="com.opensymphony.xwork2.spring.interceptor.ActionAutowiringInterceptor"/>
默認攔截器棧(20個攔截器):
<interceptor-stack name="defaultStack"> <interceptor-ref name="exception"/> <interceptor-ref name="alias"/>
指定默認攔截器棧:
<default-interceptor-ref name="defaultStack"/> <default-class-ref class="com.opensymphony.xwork2.ActionSupport" />
(2)按照以上步驟配置自定義攔截器(在struts.xml文件中進行配置):
<struts> <package name="action" namespace="/a" extends="struts-default"> <interceptors> <interceptor name="MyInter" class="pers.zhb.interceptor.InterceptorDemo2"/> <interceptor-stack name="MyStack"> <interceptor-ref name="MyInter"></interceptor-ref> <interceptor-ref name="defaultStack"></interceptor-ref><!--引入默認的20個攔截器--> </interceptor-stack> </interceptors> <default-interceptor-ref name="MyStack"></default-interceptor-ref> <action name="Demo1" class="pers.zhb.interceptor.InterceptorDemo1" method="execute"> <result name="success" type="dispatcher">/hello.jsp</result> </action> </package> </struts>
配置攔截器共分為三個步驟:注冊攔截器、注冊攔截器棧、指定默認攔截器。在注冊攔截器棧的時候需要將自己配置的攔截器放到系統的20個攔截器前面,這樣可以保證攔截器的錯誤處理功能,以便在自定義攔截器出現錯誤的時候后面的攔截器作出處理。
創建一個Action,調用自定義的攔截器:
public class InterceptorDemo1 extends ActionSupport { public String execute(){ System.out.println("我是調用攔截器的Action!"); return "success"; } }
創建攔截器:
import com.opensymphony.xwork2.ActionInvocation; import com.opensymphony.xwork2.interceptor.MethodFilterInterceptor; public class InterceptorDemo2 extends MethodFilterInterceptor { @Override protected String doIntercept(ActionInvocation actionInvocation) throws Exception { System.out.println("前處理"); actionInvocation.invoke();//放行 System.out.println("后處理"); return null; } }
其中invoke()方法可以調用攔截器。
測試結果:
9、對方法攔截的指定(即指定Action中哪些方法調用攔截器,哪些方法不調用攔截器)
(1)指定哪些方法不調用攔截器
struts.xml配置文件:
<package name="action" namespace="/a" extends="struts-default"> <interceptors> <interceptor name="MyInter" class="pers.zhb.interceptor.InterceptorDemo2"/> <interceptor-stack name="MyStack"> <interceptor-ref name="MyInter"> <param name="excludeMethods">add</param> </interceptor-ref> <interceptor-ref name="defaultStack"></interceptor-ref><!--引入默認的20個攔截器--> </interceptor-stack> </interceptors> <default-interceptor-ref name="MyStack"></default-interceptor-ref> <action name="Demo1_*" class="pers.zhb.interceptor.InterceptorDemo1" method="{1}"> <result name="success" type="dispatcher">/hello.jsp</result> </action> </package>
這里執行Action時用到了動態方法調用,畫橫線的一行指定了add方法不調用攔截器。
Action:
public class InterceptorDemo1 extends ActionSupport { public String add(){ System.out.println("ADD"); return null; } public String delete(){ System.out.println("DELETE"); return null; } public String update(){ System.out.println("UPDATE"); return null; } public String selete(){ System.out.println("SELETE"); return null; } public String execute(){ System.out.println("我是調用攔截器的Action!"); return "success"; } }
此Action中定義了四個方法,通過配置文件來指定哪些方法調用攔截器,哪些方法不調用攔截器。
調用攔截器的類:
public class InterceptorDemo2 extends MethodFilterInterceptor { @Override protected String doIntercept(ActionInvocation actionInvocation) throws Exception { System.out.println("前處理"); actionInvocation.invoke();//放行 System.out.println("后處理"); return null; } }
運行結果:
調用Action中的add方法時未調用攔截器。
(2)指定哪些方法攔截:
<param name="includeMethods">add</param>
只需修改配置文件中的如上的配置,上面的配置為:指定add方法調用攔截器,其他方法不調用攔截器。