啊最近由於逃課次數有點多,去上了計算機網絡,挺同意老師說的一句話的:“不要只學框架的api,要學習框架的設計,要去想爲什麼struts有攔截器這種東西,它怎麼實現的.....”。然而我並不打算在web開發上多費時間,以後沒打算走這一行。所以這篇博客還是以“應用”爲主,不講理論。
攔截器
攔截器是幹嘛的?顧名思義,攔截、過濾信息的。比如當jsp頁面和action(java)相互傳遞信息的時候,會經過攔截器,那我們如何自定義攔截器?攔下我們想要的信息?
在Struts2(1)這篇博客的“簡單案例”基礎上,按慣例先做個很簡單的demo引入攔截器,瞭解攔截器的大致流程。
簡單Demo
(1)src下新建一個interceptor包,新建一個helloInterceptor.java攔截器類:
public class helloInterceptor extends AbstractInterceptor {
@Override
public String intercept(ActionInvocation arg0) throws Exception {
System.out.println("Action執行之前!");
String resultString = arg0.invoke(); //執行hellojava.java這個action
System.out.println("Action執行之後");
return resultString;
}
}
(2)局部修改struts.xml文件:
首先使用<interceptors>標籤自定義攔截器helloljq,然後在action中使用<interceptor-ref>表示,當這個action開始工作前後,信息都要經過helloljq這個攔截器。
<package name="default" extends="struts-default">
<interceptors>
<interceptor name="helloljq"
class="interceptor.helloInterceptor"> </interceptor>
</interceptors>
<action name="helloword" class="action.hellojava" method="execute" >
<interceptor-ref name="helloljq"></interceptor-ref>
<result name="success" >/hellojsp.jsp</result>
</action>
</package>
運行 http://localhost:8080/自己的項目名/helloword
結果 就能在後臺觀察到,攔截器執行的順序,運行helloword這個action之前,攔截器已經再執行並後臺打印輸出“action執行前”,當action執行成功,頁面跳轉後,攔截器輸出“action執行後”。由此可見,攔截器可以處理傳遞前後的信息。
攔截器棧
假如同一個action捆綁了多個攔截器怎麼辦?它的執行順序示意圖如下:
舉例子 比如什麼過濾髒話的攔截器A、非法用戶攔截器B什麼的。
這時候我們就能能使用攔截器棧<interceptor-stack>這個標籤,例如:
<package name="default" extends="struts-default">
<!--攔截器棧的聲明-->
<interceptors>
<interceptor name="A"
class="interceptor.AInterceptor"> </interceptor>
<interceptor name="B"
class="interceptor.BInterceptor"> </interceptor>
<interceptor-stack name="ABinterceptors">
<interceptor-ref name="A"/>
<interceptor-ref name="B"/>
</interceptor-stack>
</interceptors>
<!--action中的調用-->
<action name="helloword" class="action.hellojava" method="execute" >
<interceptor-ref name="ABinterceptors"></interceptor-ref>
<result name="success" >/hellojsp.jsp</result>
</action>
</package>
它的執行順序是:先攔截器A再B然後執行helloword這個action,再觸發B,接着觸發A。
默認攔截器
如果有很多的action都要用同一個攔截器棧,使用標籤<default-interceptor-ref>,則我們可以將這個攔截棧變成默認攔截器,action中無需<interceptor-ref>調用該攔截器,action會自動調用默認攔截器,例如:
<package name="default" extends="struts-default">
<!--攔截器棧的聲明-->
<interceptors>
<interceptor name="A" class="interceptor.AInterceptor"> </interceptor>
<interceptor name="B" class="interceptor.BInterceptor"> </interceptor>
<interceptor-stack name="ABinterceptors">
<interceptor-ref name="A"/>
<interceptor-ref name="B"/>
</interceptor-stack>
</interceptors>
<!--默認攔截器-->
<default-interceptor-ref name="threeinterceptors"/>
<!--action中的調用-->
<action name="helloword" class="action.hellojava" method="execute" >
<result name="success" >/hellojsp.jsp</result>
</action>
</package>
helloword這個action會自動觸發默認攔截器。假如有個action不需要默認攔截器中的攔截器AB,只需要攔截器C的話,則action中直接調用C即可。當action有指定攔截器,即action中定義了其他攔截器引用時,則action將不再使用默認的攔截器,需要使用<interceptor-ref>調用默認攔截器。因此我們自己使用自定義攔截器的時候,爲了不出錯,最好也指定框架的默認攔截器——<interceptor-ref name="defaultStack"></interceptor-ref>。
【注】如果一個結果在多個Action或者攔截器中使用,就應該將它定義爲全局的結果。例如假如每個action返回login時,都跳轉到 login.jsp 頁面,則需要在<package>標籤中添加上:
<global-results>
<result name="login">login.jsp</result>
</global-results>
攔截器傳值
一、從用戶界面得到數值 (jsp->java)
如果jsp頁面是使用表單儲存用戶的數值的,那麼可以用request取得數值,例如在攔截器的java代碼中加上:
HttpServletRequest request = ServletActionContext.getRequest();
request.getAttribute("屬性名");
二、返回數值給用戶界面 (java->jsp)
1、java代碼中可以寫(靈活處理數值):
利用request返回數值:
HttpServletRequest request = ServletActionContext.getRequest();
request.setAttribute("屬性名","被傳遞的值");
利用session傳遞數值:
Map session = ActionContext.getContext().getSession();
session.put("屬性名", 屬性值);
2、struts.xml中可以寫(寫死的數值)
action標籤中可以加上:
<interceptor-ref name="某個被調用的攔截器名">
<param name="name屬性">"要被傳遞的數值"</param>
</interceptor-ref>
jsp頁面中可以用EL表達式取到返回的數值。