struts2拦截器
1、拦截器是基于java的反射机制的,而过滤器是基于函数回调
2、过滤器依赖与servlet容器,而拦截器不依赖与servlet容器
3、拦截器只能对action请求起作用,而过滤器则可以对几乎所有的请求起作用
4、拦截器可以访问action上下文、值栈里的对象,而过滤器不能
5、在action的生命周期中,拦截器可以多次被调用,而过滤器只能在容器初始化时被调用一次
执行顺序:过滤前 – 拦截前 – Action处理 – 拦截后 – 过滤后
一.概念
--拦截器(Interceptor)是动态拦截Action调用的对象,类似于Servlet中的过滤器,在执行Action的业务逻辑处理方法(execute())之前,struts2会首先执行在struts.xml中引用的拦截器。
--拦截器是struts2的一个重要特性,Struts2框架的大多数核心功能都是通过拦截器来实现的,像避免避免表单重复提交,类型转换,对象组装,验证,文件上传等,都是在拦截器的帮助下实现的。拦截器可以在Action执行之前和执行之后拦截调用。
二.拦截器实现原理
--struts2拦截器的基本实现相当于方法的嵌套调用。
--Struts2的拦截器机制采用了使用动作调用链的方式来嵌套调用拦截器,并将动作调用链封装在实现ActionInvocation接口的类中,而且每一个拦截器方法都有一个ActionInvocation类型的参数,在ActionInvocation接口中有一个invoke方法,在某一个拦截器方法中调用invoke方法时,就会调用下一个拦截器方法,如果当前拦截器是最后一个拦截器,就会调用Action的execute方法。
三.模拟Struts2实现一个拦截器系统
MyInvocation:
package lanjieqi.struts2; import java.util.LinkedList; import java.util.List; public class MyInvocation { private List<Interceptor> interceptors = new LinkedList<Interceptor>();// 保存拦截器对象 private Object action;// 被拦截的对象 private int interceptorIndex = 0;// 拦截器的调用索引 // 构造方法,用于注册拦截器和Action 对象 public MyInvocation(Object action, Interceptor... interceptor) { // 将拦截器对象加到interceptors中 for (int i = 0; i < interceptor.length; i++) { // 将拦截器添加到List集合 this.interceptors.add(interceptor[i]); } this.action = action; } // 执行调用链中的拦截器方法和execute方法 public void invoke() throws Exception { // 调用链中的所有拦截器方法都执行完了,开始调用execute方法 if (interceptorIndex == interceptors.size()) { try { // 通过反射技术在Action 对象中寻找execute方法如果未找到,将跑出异常 java.lang.reflect.Method method = action.getClass().getMethod( "execute"); method.invoke(getAction()); } catch (Exception e) { throw new Exception("在action中未发现execute方法"); } return; } interceptors.get(interceptorIndex++).intercept(this); } // 获得Action对象 public Object getAction() { return this.action; } }
Interceptor接口:
package lanjieqi.struts2; public interface Interceptor { //拦截器方法 public void intercept(MyInvocation invocation) throws Exception; }
Property接口:
package lanjieqi.struts2; public interface Property { public String getValue(); }
MyAction:
package lanjieqi.struts2; public class MyAction implements Property{ @Override public String getValue() { // TODO Auto-generated method stub return "属性值"; } public void execute(){ System.out.println("execute"); } }
PropertyInterceptor:相当于ModelDriven拦截器的作用
package lanjieqi.struts2; public class PropertyInterceptor implements Interceptor{ @Override public void intercept(MyInvocation invocation) throws Exception { // TODO Auto-generated method stub System.out.println("PropertyInterceptor before invoke"); //获得MyAction对象实例 Object action = invocation.getAction(); //判断MyAction类是否实现了Property接口 if(action instanceof Property){ Property property = (Property)action; //将MyAction对象转化成Property对象 //输出getValue方法返回值 System.out.println("property value:"+property.getValue()); } invocation.invoke();//调用invoke方法来执行调用链中下一个拦截器方法 System.out.println("PropertyInterceptor after invoke"); } }
MyInterceptor1:
package lanjieqi.struts2; public class MyInterceptor1 implements Interceptor { @Override public void intercept(MyInvocation invocation) throws Exception { // TODO Auto-generated method stub System.out.println("MyInterceptor1 before invoke"); invocation.invoke(); System.out.println("MyInterceptor1 after invoke"); } }
MyInterceptor2:
package lanjieqi.struts2; public class MyInterceptor2 implements Interceptor { @Override public void intercept(MyInvocation invocation) throws Exception { // TODO Auto-generated method stub System.out.println("MyInterceptor2 before invoke"); invocation.invoke(); System.out.println("MyInterceptor2 after invoke"); } }
TestInterceptor:
package lanjieqi.struts2; public class TestInterceptor { public static void main(String args[]) throws Exception { MyInterceptor1 myinterceptor1 = new MyInterceptor1(); MyInterceptor2 myinterceptor2 = new MyInterceptor2(); PropertyInterceptor propertyinterceptor = new PropertyInterceptor(); MyAction action = new MyAction(); MyInvocation myinvocation = new MyInvocation(action, myinterceptor1, myinterceptor2, propertyinterceptor); myinvocation.invoke(); } }
测试执行结果:
这个拦截器执行的全过程是:MyInterceptor1-MyInterceptor2-PropertyInterceptor-MyAction中的execute方法-PropertyInterceptor-MyInterceptor2-MyInterceptor1
PropertyInterceptor最先全部执行完成,其次是MyInterceptor2,最后是MyInterceptor1