一,要配置struts.xml文件。
world test,abc /methodFilterResult.jsp abc
要点:1,默认情况下,拦截器会拦截Action中的所有方法,这里不包括setter或getter方法。这时就可以使用方法过滤拦截器来拦截指定的方法,这是一种更加细化的拦截器的配置方式。它可以细化到拦截具体的某个方法,而不是拦截某个Action,因为拦截Action是一种粗粒度的实现方式。
2,使用includeMethods指明拦截器所要拦截的方法,使用excludeMethods指明拦截器不再拦截的方法。这里excludeMethods和includeMethods是在MethodFilterInterceptor类中定义的成员变量。
3,只要includeMethods进来的方法就一定会被拦截,而不管是否已经把它excludeMethods在外了。也就是说,includeMethods的优先级要高于excludeMethods!
4,也可以使用在上面定义拦截器的时候指定全局性过滤的方法。区别就是对方法的过滤有全局性和局部性区分,而当发生冲突时,则依照“就近原则”以局部性的配置为准。(所谓的发生冲突,指的是类似于全局中有一个includeMethods配置,而局部中也有一个includeMethods配置!)
5,还有一种情况——假设全局性过滤定义为test,而在局部性过滤中定义为test。这种情况下,前者将生效,即拦截Action中的test()方法。因为全局中配置的是拦截,局部中配置的是不拦截,二者并没有发生冲突,所以仍是以includeMethods优先级高。(可以认为在局部的配置中,已经隐含地把test继承过来了!)
6,这里衡量的所谓拦截到与否,主要可以通过查看控制台输出的语句,以判断是否执行到该拦截器内部。
二,然后写实现了Interceptor接口的自定义拦截器MyInterceptor11.java。
package com.jadyer.interceptor; import com.opensymphony.xwork2.ActionInvocation; import com.opensymphony.xwork2.interceptor.Interceptor; /** * 实现Interceptor接口的自定义拦截器 * @see 【这种方式不太常用】 */ @SuppressWarnings("serial") public class MyInterceptor11 implements Interceptor { //这里的属性名要与struts.xml配置的中的name值相同 //然后Struts2会自动将struts.xml中配置的world值赋值到这里的hello属性中 //当然,前提是要提供setter和getter方法,只要符合JavaBean的要求即可 private String hello; public String getHello() { return hello; } public void setHello(String hello) { this.hello = hello; } /** * 初始化时执行的方法 */ public void init() { System.out.println("------MyInterceptor11 init method invoked------"); System.out.println(hello); } /** * 销毁时执行的方法 */ public void destroy() { System.out.println("------MyInterceptor11 destroy method invoked------"); } //每执行一次action请求,这里的intercept()方法都会被执行一次 public String intercept(ActionInvocation invocation) throws Exception { System.out.println("------MyInterceptor11 invoked begin------"); //调用invoke()方法 //如果还有下一个拦截器的话,就执行下一个拦截器 //如果没有下一个拦截器的话,便执行Action中的方法 String result = invocation.invoke(); System.out.println("------MyInterceptor11 invoked finish------"); return result; } }
要点:1,Struts2中的拦截器是用来拦截Action的,它相当于入口和出口一样,把Action的相关方法包裹在中间。拦截器栈相当于一串拦截器,用来共同地拦截某一个Action,拦截的顺序是按照配置的顺序执行的,但是结束却是按照配置的倒序执行的。
2,也就是说首先会进入第一个拦截器,出来后再进入第二个,依次类推,最后进入Action的execute()方法。当execute()执行后,再按照相反的顺序,先回到第二个拦截器,再回到第一个,最后才回到结果视图。因此invoke()就是用来判断,若还有下一个拦截器,就调用下一个,否则直接跳到Action的execute()方法。
三,也可以写继承了AbstractInterceptor类的自定义拦截器。
package com.jadyer.interceptor; import java.util.Map; import org.apache.struts2.ServletActionContext; import com.opensymphony.xwork2.ActionInvocation; import com.opensymphony.xwork2.interceptor.AbstractInterceptor; /** * 继承AbstractInterceptor类的自定义拦截器 * @see 【这种方式比较常用】 * @see 继承AbstractInterceptor之后,就不需要再去实现init()和destroy()方法了 * @see 所以实际应用中,更多的时候还是继承AbstractInterceptor,而不是实现Interceptor * @see ------------------------------------------------------------------------------------------------------------ * @see 也可以用下面这种方式来配置 * @see* @see * @see ------------------------------------------------------------------------------------------------------------ */ @SuppressWarnings("serial") public class MyInterceptor extends AbstractInterceptor { @Override public String intercept(ActionInvocation invocation) throws Exception { System.out.println("------------ScriptHitInterceptor invoked begin------------"); //获取请求的方法名,得到的方法名不包含括号,例如methodName=preLoginCheck System.out.println("获取请求方法:methodName=" + invocation.getInvocationContext().getName()); //获取请求的参数名和参数值 Map* @see * @see* @see * @see * @see* @see * @see * @see parameters = invocation.getInvocationContext().getParameters(); for(Map.Entry entry : parameters.entrySet()){ //借助parameters根据参数名获取参数值对象,其实得到的参数值对象是一个字符串数组,该数组第一个元素即真实参数值 System.out.println("获取请求参数:" + entry.getKey() + "=" + ((String[])parameters.get(entry.getKey()))[0]); //修改下参数值 parameters.put(entry.getKey(), new String[]{"jadyer" + ((String[])parameters.get(entry.getKey()))[0]}); } //填加一个参数,这里指定其值为jadyer //Struts2之所以采用字符串数组的方式,或许是为了应对参数名或参数值相同的情况吧 parameters.put("myname", new String[]{"jadyer"}); //再次获取参数名和参数值 for(Map.Entry entry : parameters.entrySet()){ System.out.println("重新获取参数:" + entry.getKey() + "=" + ((String[])parameters.get(entry.getKey()))[0]); } //也可以通过HttpServletRequest获取真实参数值,不过它获取到的是最原始的请求参数值,而非上面我们改动过的参数值 //如果在Struts2的Action中通过ServletActionContext.getRequest().getParameter("fromBanner")获取参数值的话 //那么后台获取到的也只是原始的请求参数值fromBanner=yes,而非fromBanner=jadyeryes for(Map.Entry entry : parameters.entrySet()){ System.out.println("再次获取参数:" + entry.getKey() + "=" + ServletActionContext.getRequest().getParameter(entry.getKey())); } String result = invocation.invoke(); System.out.println("------------ScriptHitInterceptor invoked finish------------"); return result; } }
四,还可以写继承了MethodFilterInterceptor拦截器类的自定义拦截器MyInterceptor33.java。
package com.jadyer.interceptor; import com.opensymphony.xwork2.ActionInvocation; import com.opensymphony.xwork2.interceptor.MethodFilterInterceptor; /** * 继承MethodFilterInterceptor的拦截器,即方法过滤的拦截器 * @see 查看MethodFilterInterceptor的源码可知,它也是一个拦截器类,它继承了AbstractInterceptor * @see 观察它的类名,可以发现,它就是一个拦截某一个具体的方法的方法过滤拦截器 * @see 而MethodFilterInterceptor类已经自动实现好了Intercept()方法 * @see 实际上MethodFilterInterceptor类中的Intercept()方法真正执行的是它本身的一个doIntercept()抽象方法 * @see 因此,我们想要拦截某一个方法的时候,只要继承MethodFilterInterceptor类,然后实现doIntercept()便OK */ @SuppressWarnings("serial") public class MyInterceptor33 extends MethodFilterInterceptor { @Override protected String doIntercept(ActionInvocation invocation) throws Exception { System.out.println("------MyInterceptor33 invoked begin------"); String result = invocation.invoke(); System.out.println("------MyInterceptor33 invoked finish------"); return result; } }
要点:工作时经常碰到的是这种拦截器。