Struts2-MethodFilterInterceptor

這是一個Struts2.1.8.1應用,代碼如下

首先是web.xml文件

  1. <?xml version="1.0" encoding="UTF-8"?>  
  2. <web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee"  
  3.     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  
  4.     xsi:schemaLocation="http://java.sun.com/xml/ns/javaee   
  5.     http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">  
  6.     <filter>  
  7.         <filter-name>struts2</filter-name>  
  8.         <filter-class>org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter</filter-class>  
  9.     </filter>  
  10.     <filter-mapping>  
  11.         <filter-name>struts2</filter-name>  
  12.         <url-pattern>/*</url-pattern>  
  13.     </filter-mapping>  
  14.     <welcome-file-list>  
  15.         <welcome-file>methodFilter.jsp</welcome-file>  
  16.     </welcome-file-list>  
  17. </web-app>  

然後用於提交方法過濾測試的methodFilter.jsp頁面

  1. <%@ page language="java" pageEncoding="UTF-8"%>  
  2. <%@ taglib prefix="s" uri="/struts-tags"%>  
  3. <s:form action="methodFilter" theme="simple">  
  4.     您可以直接點擊Submit提交請求,然後在控制檯查看輸出情況<br/>  
  5.     <s:submit value="我要測試方法過濾攔截器"/>  
  6. </s:form>  

然後是用於顯示方法過濾結果的methodFilterResult.jsp頁面

  1. <%@ page pageEncoding="UTF-8"%>  
  2. <h2>請移步控制檯查看輸出情況</h2>  

然後是struts.xml文件

  1. <?xml version="1.0" encoding="UTF-8" ?>  
  2. <!DOCTYPE struts PUBLIC  
  3.         "-//Apache Software Foundation//DTD Struts Configuration 2.1//EN"  
  4.         "http://struts.apache.org/dtds/struts-2.1.dtd">  
  5. <struts>  
  6.     <package name="methodFilter" extends="struts-default">  
  7.         <interceptors>  
  8.             <interceptor name="myInterceptor11" class="com.jadyer.interceptor.MyInterceptor11">  
  9.                 <param name="hello">world</param>  
  10.             </interceptor>  
  11.             <!-- <param name="hello">world</param>表示爲攔截器增加一個名爲hello值爲world的屬性 -->  
  12.             <!-- 但是這裏也只是爲hello賦了初值爲world。如若在下面的<action/>中配置使用該攔截器的時候 -->  
  13.             <!-- 增加了<param name="hello">welcome</param>,則最後攔截器類中hello屬性值即爲welcome -->  
  14.             <interceptor name="myInterceptor22" class="com.jadyer.interceptor.MyInterceptor22"/>  
  15.             <interceptor name="myInterceptor33" class="com.jadyer.interceptor.MyInterceptor33">  
  16.                 <param name="includeMethods">test,abc</param>  
  17.             </interceptor>  
  18.         </interceptors>  
  19.         <action name="methodFilter" class="com.jadyer.action.MethodFilterAction" method="test">  
  20.             <result name="success">/methodFilterResult.jsp</result>  
  21.             <interceptor-ref name="defaultStack"/>  
  22.             <interceptor-ref name="myInterceptor11"/>  
  23.             <interceptor-ref name="myInterceptor22"/>  
  24.             <interceptor-ref name="myInterceptor33">  
  25.                 <param name="includeMethods">abc</param>  
  26.             </interceptor-ref>  
  27.         </action>  
  28.     </package>  
  29. </struts>  
  30. <!-- *********************【方法過濾攔截器的使用】********************************************** -->  
  31. <!-- 默認的情況下,攔截器會攔截Action中的所有的方法,這裏不包括setter或getter方法 -->  
  32. <!-- 這時就可以使用方法過濾攔截器來攔截指定的方法,這是一種更加細化的攔截器的配置方式 -->  
  33. <!-- 它可以細化到攔截具體的某個方法。而不是攔截某個Action,因爲攔截Action是一種粗粒度的實現方式 -->  
  34. <!-- 使用includeMethods指明攔截器所要攔截的方法。使用excludeMethods指明攔截器不再攔截的方法 -->  
  35. <!-- 這裏excludeMethods和includeMethods是在MethodFilterInterceptor類中定義的成員變量 -->  
  36. <!-- 而且只要includeMethods進來的方法就一定會被攔截,而不管是否已經把它excludeMethods在外了 -->  
  37. <!-- 也就是說includeMethods的優先級要高於excludeMethods -->  
  38. <!-- 也可以使用<param name="includeMethods"/>在上面定義攔截器的時候指定全局性過濾的方法 -->  
  39. <!-- 區別就是對方法的過濾有全局性和局部性區分。而當發生衝突時,則依照【就近原則】以局部性的配置爲準 -->  
  40. <!-- 所謂的發生衝突,指的是類似於全局中有一個includeMethods配置,而局部中也有一個includeMethods配置 -->  
  41. <!-- 另外,還有一種情況,假設全局性過濾定義爲<param name="includeMethods">test</param> -->  
  42. <!-- 而在局部性過濾中定義爲<param name="excludeMethods">test</param> -->  
  43. <!-- 這種情況下,<param name="includeMethods">test</param>將生效,即攔截Action中的test()方法 -->  
  44. <!-- 這個時候全局中配置的是攔截,局部中配置的是不攔截,二者並沒有發生衝突,所以仍是以includeMethods優先級高 -->  
  45. <!-- 可以認爲在局部的配置中,已經隱含的把<param name="includeMethods">test</param>繼承過來了 -->  
  46. <!-- 補充:這裏衡量的所謂攔截到與否,主要可以通過查看控制檯輸出的語句,以判斷是否執行到該攔截器內部 -->  
  47. <!-- **************************************************************************************** -->  

實現了Interceptor接口的自定義攔截器MyInterceptor11.java

  1. package com.jadyer.interceptor;  
  2.   
  3. import com.opensymphony.xwork2.ActionInvocation;  
  4. import com.opensymphony.xwork2.interceptor.Interceptor;  
  5.   
  6. /** 
  7.  * 實現Interceptor接口的自定義攔截器 
  8.  * @see 【這種方式不太常用】 
  9.  */  
  10. @SuppressWarnings("serial")  
  11. public class MyInterceptor11 implements Interceptor {  
  12.     //這裏的屬性名要與struts.xml配置的<param name=""/>中的name值相同  
  13.     //然後Struts2會自動將struts.xml中配置的world值賦值到這裏的hello屬性中  
  14.     //當然,前提是要提供setter和getter方法,只要符合JavaBean的要求即可  
  15.     private String hello;  
  16.   
  17.     public String getHello() {  
  18.         return hello;  
  19.     }  
  20.     public void setHello(String hello) {  
  21.         this.hello = hello;  
  22.     }  
  23.   
  24.     /** 
  25.      * 初始化時執行的方法 
  26.      */  
  27.     public void init() {  
  28.         System.out.println("------MyInterceptor11 init method invoked------");  
  29.         System.out.println(hello);  
  30.     }  
  31.     /** 
  32.      * 銷燬時執行的方法 
  33.      */  
  34.     public void destroy() {  
  35.         System.out.println("------MyInterceptor11 destroy method invoked------");  
  36.     }  
  37.   
  38.     //每執行一次action請求,這裏的intercept()方法都會被執行一次  
  39.     public String intercept(ActionInvocation invocation) throws Exception {  
  40.         System.out.println("------MyInterceptor11 invoked begin------");  
  41.         //調用invoke()方法  
  42.         //如果還有下一個攔截器的話,就執行下一個攔截器  
  43.         //如果沒有下一個攔截器的話,便執行Action中的方法  
  44.         String result = invocation.invoke();  
  45.         System.out.println("------MyInterceptor11 invoked finish------");  
  46.         return result;  
  47.     }  
  48. }  
  49. /********************【淺析Struts2的攔截器】***********************************************************/  
  50. //Struts2中的攔截器,實際上就是用來攔截Action的。它就相當於入口和出口一樣,把Action的相關方法包裹在中間了  
  51. //過濾器可以組成過濾器鏈,也就是有多個過濾器來過濾相同的東西。攔截器同樣也有攔截器鏈,在Struts2中稱爲攔截器棧  
  52. //攔截器棧相當於一串攔截器,用來共同的攔截某一個Action。攔截的順序是按照配置的順序執行的  
  53. //假設先配置的是myInterceptor11,後配置的是myInterceptor22  
  54. //所以在執行時,先執行myInterceptor11,後執行myInterceptor22  
  55. //但是在結束時,先執行myInterceptor22,後執行myInterceptor11  
  56. //就好像進入一個有兩道門的房間一樣,進去的順序和出來的順序正好相反  
  57. //也就是說它首先會進入第一個攔截器,出來後再進入第二個攔截器,依此類推,最後進入Action的execute()方法  
  58. //當execute()執行後,再按照相反的順序,先回到第二個攔截器,再回到第一個攔截器,最後纔回到結果視圖  
  59. //因此invoke()就是用來判斷,若還有下一個攔截器,就調用下一個攔截器。否則,直接跳到Action的execute()方法  
  60. /********************【Struts2的默認攔截器】***********************************************************/  
  61. //實際上可以把Struts2看成是一個空的容器。就是因爲裏面配置了大量的攔截器,導致了我們的請求需要一層一層的通過這些攔截器  
  62. //然後它會處理我們的請求,並根據我們的配置,把它所感興趣的東西解析出來。如果出現問題,它會放到錯誤消息裏面去  
  63. /****************************************************************************************************/  

繼承了AbstractInterceptor類的自定義攔截器MyInterceptor22.java

  1. package com.jadyer.interceptor;  
  2.   
  3. import java.util.Map;  
  4.   
  5. import org.apache.struts2.ServletActionContext;  
  6.   
  7. import com.opensymphony.xwork2.ActionInvocation;  
  8. import com.opensymphony.xwork2.interceptor.AbstractInterceptor;  
  9. /** 
  10.  * 繼承AbstractInterceptor類的自定義攔截器 
  11.  * @see 【這種方式比較常用】 
  12.  * @see 繼承AbstractInterceptor之後,就不需要再去實現init()和destroy()方法了 
  13.  * @see 所以實際應用中,更多的時候還是繼承AbstractInterceptor,而不是實現Interceptor 
  14.  * @see ------------------------------------------------------------------------------------------------------------ 
  15.  * @see 也可以用下面這種方式來配置 
  16.  * @see <package name="scriptHit" extends="struts-default"> 
  17.  * @see         <interceptors> 
  18.  * @see             <interceptor name="ScriptHitInterceptor" class="com.jadyer.interceptor.ScriptHitInterceptor"/> 
  19.  * @see             <interceptor-stack name="scriptHitStack"> 
  20.  * @see                 <interceptor-ref name="ScriptHitInterceptor"/> 
  21.  * @see                 <interceptor-ref name="defaultStack"/> 
  22.  * @see             </interceptor-stack> 
  23.  * @see         </interceptors> 
  24.  * @see         <default-interceptor-ref name="scriptHitStack"/> 
  25.  * @see </package> 
  26.  * @see ------------------------------------------------------------------------------------------------------------ 
  27.  * @editor Mar 6, 2013 2:16:11 PM 
  28.  * @author 玄玉<http://blog.csdn/net/jadyer> 
  29.  */  
  30. @SuppressWarnings("serial")  
  31. public class MyInterceptor22 extends AbstractInterceptor {  
  32.     /** 
  33.      * http://127.0.0.1:8088/jfb/web/preLoginCheck?phoneNo=302<script>alert(1)</script>225&fromBanner=yes 
  34.      * 控制檯輸出如下 
  35.      * @see 獲取請求方法:methodName=preLoginCheck 
  36.      * @see 獲取請求參數:phoneNo=302<script>alert(1)</script>225 
  37.      * @see 獲取請求參數:fromBanner=yes 
  38.      * @see 重新獲取參數:phoneNo=jadyer302<script>alert(1)</script>225 
  39.      * @see 重新獲取參數:fromBanner=jadyeryes 
  40.      * @see 重新獲取參數:myname=jadyer 
  41.      * @see 再次獲取參數:phoneNo=302<script>alert(1)</script>225 
  42.      * @see 再次獲取參數:fromBanner=yes 
  43.      * @see 再次獲取參數:myname=null 
  44.      */  
  45.     @Override  
  46.     public String intercept(ActionInvocation invocation) throws Exception {  
  47.         System.out.println("------------ScriptHitInterceptor invoked begin------------");  
  48.           
  49.         //獲取請求的方法名,得到的方法名不包含括號,例如methodName=preLoginCheck  
  50.         System.out.println("獲取請求方法:methodName=" + invocation.getInvocationContext().getName());  
  51.           
  52.         //獲取請求的參數名和參數值  
  53.         Map<string object=""> parameters = invocation.getInvocationContext().getParameters();  
  54.         for(Map.Entry<string object=""> entry : parameters.entrySet()){  
  55.             //藉助parameters根據參數名獲取參數值對象,其實得到的參數值對象是一個字符串數組,該數組第一個元素即真實參數值  
  56.             System.out.println("獲取請求參數:" + entry.getKey() + "=" + ((String[])parameters.get(entry.getKey()))[0]);  
  57.             //修改下參數值  
  58.             parameters.put(entry.getKey(), new String[]{"jadyer" + ((String[])parameters.get(entry.getKey()))[0]});  
  59.         }  
  60.           
  61.         //填加一個參數,這裏指定其值爲jadyer  
  62.         //Struts2之所以採用字符串數組的方式,或許是爲了應對參數名或參數值相同的情況吧  
  63.         parameters.put("myname"new String[]{"jadyer"});  
  64.           
  65.         //再次獲取參數名和參數值  
  66.         for(Map.Entry<string object=""> entry : parameters.entrySet()){  
  67.             System.out.println("重新獲取參數:" + entry.getKey() + "=" + ((String[])parameters.get(entry.getKey()))[0]);  
  68.         }  
  69.           
  70.         //也可以通過HttpServletRequest獲取真實參數值,不過它獲取到的是最原始的請求參數值,而非上面我們改動過的參數值  
  71.         //如果在Struts2的Action中通過ServletActionContext.getRequest().getParameter("fromBanner")獲取參數值的話  
  72.         //那麼後臺獲取到的也只是原始的請求參數值fromBanner=yes,而非fromBanner=jadyeryes  
  73.         for(Map.Entry<string object=""> entry : parameters.entrySet()){  
  74.             System.out.println("再次獲取參數:" + entry.getKey() + "=" + ServletActionContext.getRequest().getParameter(entry.getKey()));  
  75.         }  
  76.           
  77.         String result = invocation.invoke();  
  78.         System.out.println("------------ScriptHitInterceptor invoked finish------------");  
  79.         return result;  
  80.     }  
  81. }</string></string></string></string></http:>  

繼承了MethodFilterInterceptor攔截器類的自定義攔截器MyInterceptor33.java

  1. package com.jadyer.interceptor;  
  2.   
  3. import com.opensymphony.xwork2.ActionInvocation;  
  4. import com.opensymphony.xwork2.interceptor.MethodFilterInterceptor;  
  5.   
  6. /** 
  7.  * 繼承MethodFilterInterceptor的攔截器,即方法過濾的攔截器 
  8.  * @see 查看MethodFilterInterceptor的源碼可知,它也是一個攔截器類,它繼承了AbstractInterceptor 
  9.  * @see 觀察它的類名,可以發現,它就是一個攔截某一個具體的方法的方法過濾攔截器 
  10.  * @see 而MethodFilterInterceptor類已經自動實現好了Intercept()方法 
  11.  * @see 實際上MethodFilterInterceptor類中的Intercept()方法真正執行的是它本身的一個doIntercept()抽象方法 
  12.  * @see 因此,我們想要攔截某一個方法的時候,只要繼承MethodFilterInterceptor類,然後實現doIntercept()便OK 
  13.  */  
  14. @SuppressWarnings("serial")  
  15. public class MyInterceptor33 extends MethodFilterInterceptor {  
  16.     @Override  
  17.     protected String doIntercept(ActionInvocation invocation) throws Exception {  
  18.         System.out.println("------MyInterceptor33 invoked begin------");  
  19.         String result = invocation.invoke();  
  20.         System.out.println("------MyInterceptor33 invoked finish------");  
  21.         return result;  
  22.     }  
  23. }  

最後是用到的Action類

  1. package com.jadyer.action;  
  2.   
  3. import com.opensymphony.xwork2.ActionSupport;  
  4.   
  5. @SuppressWarnings("serial")  
  6. public class MethodFilterAction extends ActionSupport{  
  7.     public String test() throws Exception {  
  8.         System.out.println("------test() is invoked------");  
  9.         return SUCCESS;  
  10.     }  
  11.       
  12.     public String abc() throws Exception {  
  13.         System.out.println("------abc() is invoked------");  
  14.         return SUCCESS;  
  15.     }  
  16.   
  17.     @Override  
  18.     public String execute() throws Exception {  
  19.         System.out.println("------execute() is invoked------");  
  20.         return SUCCESS;  
  21.     }  
  22. }  

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章