目錄
基本概念及原理
含義:
Struts 2攔截器,是Struts2的核心和基礎。
爲AOP的一種實現,底層通過動態代理動態完成。反射。
訪問action之後,需要經過層層攔截器。
完成某些功能的類,以可插拔的方式放在配置前,後。
官方定義:
動態攔截Action調用的對象,提供機制,定義代碼,使其在Action前後被調用,也可以在Action執行之前阻止其執行。同時提供一種可以提取Action中可重用的方式。
攔截器棧:多個攔截器組合的集合體,將這些攔截器按照一定的順序鏈接成鏈。
圖:後進先出棧
攔截器原理:和過濾器的功能類似,一個攔截器在一個攔截棧中有什麼功能:1,可以調用下方的攔截器,有時可以判斷請求是否通過,下面如果沒有攔截器的話調用資源Action。
攔截器代碼:在struts-default.xml中查看。
interceptors器;
interceptor-stack棧;
default-interceptor-ref默認攔截器配置。
典型的責任鏈模式,職責鏈,判斷在運行過程中實時選擇。 代表:異常
每個元素有不同職責,將他們納入鏈式結構,每個元素負責鏈式結構下一個元素的執行調用。
思想:將複雜的系統分而治之,使每個部分的邏輯能夠高度重用並增強他的拓展性。
自定義攔截器:
三個步驟:
1.直接或間接實現接口,(適配器模式)com.opensymphony.xwork2.interceptor.Interceptor,實現一個接口必須實現接口中的所有方法。如圖:
或者繼承繼承類 com.opensymphony.xwork2.interceptor.AbstractInterceptor實現一個繼承類只需要實現需要的方法。
2,通過<interceptor>元素來定義攔截器
3,通過<interceptor-ref>元素使用攔截器
struts.xml中 定義攔截器,定義在action標籤之前,並在action中配置攔截器。新建Invocation。先定義一個新的攔截器類MyInterceptor,繼承Interceptor接口中的多個方法,也可繼承AbstractInterceptor中的方法,繼承到的方法,將intercept方法中在攔截器獲得攔截結果的前後打入輸出,調試程序觀察出攔截器出入的順序。
public String intercept(ActionInvocation invocation) throws Exception {
System.out.println("method start");
String result=invocation.invoke();
System.out.println("method end");
return result;
}
配置struts.xml攔截器的代碼:
<interceptors>
<interceptor name="inter01" class="com.it.struts.inter.MyInterceptor"></interceptor>
</interceptors>
使用攔截器
加入攔截器出現了問題,當引用自定義攔截器時,默認攔截器將失效。此時需要在struts.xml中手動引用默認攔截器。
<default-interceptor-ref name="defaultStack"/>
在action標籤中添加默認攔截器的引用代碼:
<interceptor-ref name="defaultStack"></interceptor-ref>
攔截器1成功,並且按出入順序打印出標記:
攔截棧的運用:
也可以將兩條引用語句從action配置中取出並放入攔截棧中,稱爲自定義攔截棧,命名爲myStack。
<interceptors>
<!-- 自定義攔截器 -->
<interceptor name="inter01" class="com.it.struts.inter.MyInterceptor"></interceptor>
<!-- 自定義攔截棧 -->
<interceptor-stack name="myStack">
<interceptor-ref name="inter01"></interceptor-ref>
<interceptor-ref name="defaultStack"></interceptor-ref>
</interceptor-stack>
</interceptors>
並在action中引用myStack攔截棧。
<interceptor-ref name="myStack"></interceptor-ref>
在定義兩個攔截器的時候,配置完成後,運行獲得結果。
獲取數據的順序爲後進先出,符合攔截棧的基本特性。
提出問題:在package中的多個action想要引用同名攔截棧myStack,只需要在action標籤前面添加語句:
<default-interceptor-ref name="myStack"></default-interceptor-ref>
添加後action中的調用棧語句可以刪除。
攔截器對所有方法都會攔截,但是隻想要攔截單獨的方法。提供MethodFilterInterceptor類
其中有兩個方法:exclude爲顯示想要攔截的方法,include爲顯示不想要攔截的方法。
在MethodFilterInterceptor類中有兩個的方法,攔截和不攔截,在自定義攔截器中你想要操作的攔截器標籤下添加param標籤:
<interceptor name="inter03" class="com.it.struts.inter.MyInterceptor3">
<param name="excludeMethods">login</param></interceptor>
表示攔截器3不進行攔截,此時就不會通過攔截器3。includeMethods方法同理。
重複提交數據:
在提交數據之後,刷新頁面會使數據再次提交,數據會提交兩次,造成錯誤。
可以用重定向sendRecdient,將地址定向到新的頁面。但是某些情況只能使用請求轉發Dispacther。
如何解決:在第一次打開頁面後,向session中存值,同時保存,提交頁面時將提交頁面的值和session的值進行比對,如果一致,代表第一次提交,運行進入Action,第一次提交後session清空,第二次打開頁面,表單中的值還在,session中的值已經沒有了,兩個對比之下不同,便可以跳轉至錯誤頁面。
解決方法:
使用Strut2框架中自帶的tokenInterceptor攔截器。
1,在提交頁面如登錄頁面表單中加入token標記。
在form表單中添加 <s:token></s:token>標籤。
2,在struts.xml中配置tokenInterceptor攔截器和配置invoke.token信息。
在Struts2中有一個攔截器token,需要配置進棧。
<interceptor name="token" class="org.apache.struts2.interceptor.TokenInterceptor"/>
最後在token接口中找到結果名稱,類型爲redirect。
<result name="invalid.token" type="redirect">login.jsp</result>
這樣,就可以解決在Struts2框架中關於數據由於重複刷新而導致重複提交數據的情況。