Struts2中的MethodFilterInterceptor

来源:互联网 发布:手机版网络维护软件 编辑:程序博客网 时间:2024/05/17 03:11

这是一个Struts2.1.8.1应用,代码如下

首先是web.xml文件

[xhtml] view plaincopyprint?
  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页面

[xhtml] view plaincopyprint?
  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页面

[xhtml] view plaincopyprint?
  1. <%@ page pageEncoding="UTF-8"%>  
  2. <h2>请移步控制台查看输出情况</h2>  

然后是struts.xml文件

[xhtml] view plaincopyprint?
  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

[java] view plaincopyprint?
  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

[java] view plaincopyprint?
  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

[java] view plaincopyprint?
  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类

[java] view plaincopyprint?
  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. }  

原创粉丝点击