Struts2的基石(攔截器)

攔截器(Interceptor)是Struts2的基石,攔截器的主要作用是在Action執行之前和Result執行之後進行一些特定功能的處理機制。


如圖,攔截器是用來負責在Action執行之前和Result執行之後處理一些功能的類。每個不同的攔截器,它們分別執行不同的功能處理,而運行的時機就是在Action執行之前和Result執行之後,需要注意的是在執行Action之前和Result之後,攔截器的執行順序是正好相反的。

一、攔截器的好處

  • 1.簡化Action的實現,可以把很多功能從Action中獨立出來,大量減少了Action的代碼書寫。
  • 2.功能更單一,把功能從Action中分離出來,分散到不同的攔截器裏面,這樣使每個攔截器和Action的功能更加單一,便於維護。
  • 3.通用代碼模塊化和重用性,把Action中的功能分離出來,放到攔截器去實現,這樣就能實現多個Action中通用的代碼進行模塊化,多個Action公用一個攔截器
  • 4.實現AOP,Struts2通過攔截器實現了AOP(面向切面編程),AOP是一種分散實現關注功能的編程模式。
  • 攔截器將通用需求功能從不相關的Action之中分離出來,能夠使得很多Action共享同一個行爲,一旦行爲發生變化,不必修改很多Action,只要修改這個行爲就可以了。
  • 二、預定義的攔截器
  • 在Struts-default.xml中,提供了很多預定義的攔截器
  • [html] view plaincopy
    1. <interceptors>  
    2.             <interceptor name="alias" class="com.opensymphony.xwork2.interceptor.AliasInterceptor"/>  
    3.             <interceptor name="autowiring" class="com.opensymphony.xwork2.spring.interceptor.ActionAutowiringInterceptor"/>  
    4.             <interceptor name="chain" class="com.opensymphony.xwork2.interceptor.ChainingInterceptor"/>  
    5.             <interceptor name="conversionError" class="org.apache.struts2.interceptor.StrutsConversionErrorInterceptor"/>  
    6.             <interceptor name="cookie" class="org.apache.struts2.interceptor.CookieInterceptor"/>  
    7.             <interceptor name="clearSession" class="org.apache.struts2.interceptor.ClearSessionInterceptor" />  
    8.             <interceptor name="createSession" class="org.apache.struts2.interceptor.CreateSessionInterceptor" />  
    9.             <interceptor name="debugging" class="org.apache.struts2.interceptor.debugging.DebuggingInterceptor" />  
    10.             <interceptor name="externalRef" class="com.opensymphony.xwork2.interceptor.ExternalReferencesInterceptor"/>  
    11.             <interceptor name="execAndWait" class="org.apache.struts2.interceptor.ExecuteAndWaitInterceptor"/>  
    12.             <interceptor name="exception" class="com.opensymphony.xwork2.interceptor.ExceptionMappingInterceptor"/>  
    13.             <interceptor name="fileUpload" class="org.apache.struts2.interceptor.FileUploadInterceptor"/>  
    14.             <interceptor name="i18n" class="com.opensymphony.xwork2.interceptor.I18nInterceptor"/>  
    15.             <interceptor name="logger" class="com.opensymphony.xwork2.interceptor.LoggingInterceptor"/>  
    16.             <interceptor name="modelDriven" class="com.opensymphony.xwork2.interceptor.ModelDrivenInterceptor"/>  
    17.             <interceptor name="scopedModelDriven" class="com.opensymphony.xwork2.interceptor.ScopedModelDrivenInterceptor"/>  
    18.             <interceptor name="params" class="com.opensymphony.xwork2.interceptor.ParametersInterceptor"/>  
    19.             <interceptor name="actionMappingParams" class="org.apache.struts2.interceptor.ActionMappingParametersInteceptor"/>  
    20.             <interceptor name="prepare" class="com.opensymphony.xwork2.interceptor.PrepareInterceptor"/>  
    21.             <interceptor name="staticParams" class="com.opensymphony.xwork2.interceptor.StaticParametersInterceptor"/>  
    22.             <interceptor name="scope" class="org.apache.struts2.interceptor.ScopeInterceptor"/>  
    23.             <interceptor name="servletConfig" class="org.apache.struts2.interceptor.ServletConfigInterceptor"/>  
    24.             <interceptor name="sessionAutowiring" class="org.apache.struts2.spring.interceptor.SessionContextAutowiringInterceptor"/>  
    25.             <interceptor name="timer" class="com.opensymphony.xwork2.interceptor.TimerInterceptor"/>  
    26.             <interceptor name="token" class="org.apache.struts2.interceptor.TokenInterceptor"/>  
    27.             <interceptor name="tokenSession" class="org.apache.struts2.interceptor.TokenSessionStoreInterceptor"/>  
    28.             <interceptor name="validation" class="org.apache.struts2.interceptor.validation.AnnotationValidationInterceptor"/>  
    29.             <interceptor name="workflow" class="com.opensymphony.xwork2.interceptor.DefaultWorkflowInterceptor"/>  
    30.             <interceptor name="store" class="org.apache.struts2.interceptor.MessageStoreInterceptor" />  
    31.             <interceptor name="checkbox" class="org.apache.struts2.interceptor.CheckboxInterceptor" />  
    32.             <interceptor name="profiling" class="org.apache.struts2.interceptor.ProfilingActivationInterceptor" />  
    33.             <interceptor name="roles" class="org.apache.struts2.interceptor.RolesInterceptor" />  
    34.             <interceptor name="jsonValidation" class="org.apache.struts2.interceptor.validation.JSONValidationInterceptor" />  
    35.             <interceptor name="annotationWorkflow" class="com.opensymphony.xwork2.interceptor.annotations.AnnotationWorkflowInterceptor" />  
    36.             <interceptor name="multiselect" class="org.apache.struts2.interceptor.MultiselectInterceptor" />  
    37. </interceptors>  

幾個常用的攔截器

1.params攔截器,把請求參數設置到相應的Action的屬性去的,並自動進行類型轉換。

2:staticParams攔截器,將struts.xml配置文件裏定義的Action參數,設置到對應的Action實例中,Action參數使用<param>標籤,是<action>標籤的子元素。

注意:如果request裏面有account參數,而struts.xml中也有account參數,Action中最終的值是誰?

       在Action初始化過後,就會把struts.xml中配置的數據設置到Action實例中相應的屬性上去。然後,把用戶請求的數據設置到Action實例中相應的屬性上去。

3.prepare攔截器,在Action執行之前調用Action的prepare()方法,這個方法是用來準備Action執行之前要做的工作。它要求我們的Action必需實現com.opensymphony.xwork2.Preparable接口,一般都是與ModelDriven一起使用

4.modelDriven攔截器,如果Action實現ModelDriven接口,它將getModel()取得的模型對象存入OgnlValueStack中

5.chain攔截器,將前一個執行結束的Action屬性設置到當前的Action中。它被用在ResultType爲“chain”所指定的結果的Action中,該結果Action對象會從值棧中獲得前一個Action對應的屬性,它實現Action鏈之間的數據傳遞

6.validation攔截器,調用驗證框架讀取 *-validation.xml文件,並且應用在這些文件中聲明的校驗

7.token攔截器(令牌攔截器),覈對當前Action請求(request)的有效標識,防止重複提交。使用標籤<s:token>可以生成表單令牌,該標籤會在session中設置一個預期的值並且在表單中創建一個隱藏的input字段。Token攔截器會檢查這個令牌,如果不合法,將不會執行action,注意這個攔截器需要手工添加,還需要配置一個invalid.token的result。

8.timer攔截器,記錄ActionInvocation餘下部分執行的時間,並做爲日誌信息記錄下來,便於查找性能優化。

預定義的攔截器棧

在struts-default.xml中給出了Struts2的默認的預定義攔截器棧defaultStack

  • [java] view plaincopy
    1. <interceptors>  
    2. <interceptor>。。。。  
    3. <interceptor-stack>。。。  
    4. <default-interceptor-ref>。。。。  
    5. </interceptors>  
    1.<interceptor>用來定義一個攔截器,僅僅是一個定義,還沒有被Action來引用它。name屬性作爲唯一標誌,而class屬性就是這個攔截器的實現類的全類名。攔截器的實現類都應該是com.opensymphony.xwork2.interceptor.Interceptor這個接口的實現類
  • 2.<interceptor-stack>定義了一個攔截器棧,這個棧中可以引用其他已經定義好的攔截器。攔截器棧簡化了動作類Action在引用攔截器時的操作。

    因爲大多數動作類Action在引用攔截器的時候都不會僅僅引用一個攔截器,而是引用一組攔截器。Action在引用的時候,只需要引用這個攔截器棧就可以了,而不是引用每一個攔截器

    攔截器的調用順序

  • (1).要找它自己有沒有聲明攔截器的引用,即<action>元素有沒有<interceptor-ref>子元素,如果有,則不用繼續再找,如果沒有,(2)。

    (2):在這個<action>所在的包有沒有聲明默認的攔截器引用,即<package>元素的<default-interceptor-ref>子元素, 如果有,則不用繼續再找,直接使用這些攔截器,如果沒有,(3)。

  •  (3):遞歸地尋找當前包的父包有沒有聲明默認的攔截器引用,直到找到有攔截器引用就爲止

  • 注意:三者是覆蓋關係


  • 三、自定義攔截器
所有的攔截器都要實現com.opensymphony.xwork2.interceptor.Interceptor接口

[java] view plaincopy
  1. public interface Interceptor {  
  2.     void destroy();  
  3.     void init();  
  4.     String intercept(ActionInvocation invocation) throws Exception;  
  5. }  
自定義登錄攔截器

判斷用戶是否登錄,如果沒有返回登錄頁面

[java] view plaincopy
  1. public class PermissionInterceptor implements Interceptor {  
  2.   
  3.     private static final long serialVersionUID = 1L;  
  4.   
  5.     @Override  
  6.     public void destroy() {  
  7.     }  
  8.   
  9.     @Override  
  10.     public void init() {  
  11.     }  
  12.   
  13.     @Override  
  14.     public String intercept(ActionInvocation invocation) throws Exception {  
  15.   
  16.         HttpSession session = ServletActionContext.getRequest().getSession();  
  17.         Object obj = session.getAttribute("user");  
  18.         if(obj==null){  
  19.             return "login";  
  20.         }else{  
  21.             return invocation.invoke();  
  22.         }  
  23.     }  
  24.   
  25. }  

配置struts.xml文件

創建父包

[html] view plaincopy
  1. <package name="mydefault" extends="struts-default">  
  2.         <interceptors>  
  3.             <interceptor name="PermissionInterceptor" class="cn.cil.interceptor.PermissionInterceptor"></interceptor>  
  4.             <interceptor-stack name="mydefaultStack">  
  5.                 <interceptor-ref name="PermissionInterceptor"></interceptor-ref>  
  6.                 <interceptor-ref name="defaultStack"></interceptor-ref>  
  7.             </interceptor-stack>  
  8.         </interceptors>  
  9.     </package>  
有需要使用自定義的權限攔截器,就可以繼承這個pacjage

[html] view plaincopy
  1. <package name="struts" namespace="/user" extends="mydefault">  
  2.       
  3.         <action name="user_*" class="cn.cil.domain.User" method="{1}">  
  4.         <interceptor-ref name="mydefaultStack"></interceptor-ref>  
  5.             <result>/listUsers.jsp </result>  
  6.             <result name="input">/{1}.jsp</result>  
  7.             <result name="login">/login.jsp</result>  
  8.         </action>  
  9.         <action name="download" class="cn.cil.domain.User" method="download">  
  10.             <interceptor-ref name="mydefaultStack"></interceptor-ref>  
  11.             <result type="stream" name="success">  
  12.                     <param name="contentType">application/octet-stream</param>  
  13.                     <param name="inputStream">inputStream</param>  
  14.                     <param name="contentDisposition">attachment;filename=${filename}</param>  
  15.             </result>  
  16.             <result name="login">/login.jsp</result>  
  17.         </action>  
  18. </package>  

向攔截器傳入參數

同一個攔截器爲不同的Action服務的時候,需要根據傳入的參數進行處理上的變化。比如說,一個記錄日誌的攔截器,可以根據配置來決定到底把日誌記錄在數據庫還是文件裏面。

可以把這種配置數據作爲一個參數,在配置的時候設置值,會自動傳入攔截器中

[html] view plaincopy
  1. <interceptor-ref name=“myInterceptor”>  
  2.                 <param name="param">params</param>  
  3.         </interceptor-ref>  

[java] view plaincopy
  1. public class MyInterceptor implements Interceptor{  
  2.     private String param;  
  3.     public void setParam(String param) {  
  4.         this.param = param;  
  5.     }  
  6.     public void destroy() {  
  7.     }  
  8.     public void init() {  
  9.     }  
  10.     public String intercept(ActionInvocation invocation) throws Exception {  
  11.         System.out.println("接到param的參數=="+this.param);  
  12.         if("params".equalsIgnoreCase(this.param)){  
  13.             System.out.println("記錄日誌到數據庫");  
  14.         }else{  
  15.             System.out.println("記錄日誌到文件");  
  16.         }  
  17.         String result = invocation.invoke();  
  18.         return result;  
  19.     }     
  20. }  
注意setter方法,在初始化這個攔截器的時候,Struts2就會反射的調用對應的setter,把在<param>元素中配置的值設置到param屬性上去
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章