1、拦截器简介
拦截器,在AOP(Aspect-Oriented Programming)中用于在某个方法或字段被访问之前,进行拦截然后在之前或之后加入某些操作。拦截是AOP的一种实现策略。
拦截器是动态拦截Action调用的对象。它提供了一种机制可以使开发者可以定义在一个action执行的前后执行的代码,也可以在一个action执行前阻止其执行。同时也是提供了一种可以提取action中可重用的部分的方式。
拦截器栈(Interceptor Stack)类似于过滤器链。拦截器栈就是将拦截器按一定的顺序联结成一条链。在访问被拦截的方法或字段时,拦截器栈的拦截器就会按其之前定义的顺序被调用。也可以叫做拦截器链(Interceptor Stack),拦截器栈一词更明确的表名了连接器链的实现方式。
2、拦截器的原理
1)联系:
Struts2 中的拦截器和 servelt 中的过滤器是非常的相似的。过滤器 public interface Filter 接口里面有三个方法:
- init(FilterConfig filterConfig),
- destroy(),
- doFilter(ServletRequest request, ServletResponse response, FilterChain chain)。
而在 com.opensymphony.xwork2.interceptor 中,里面有个 Interceptor 这是个接口,里面也有三个方法,有 init, destroy 和 intercept 三个方法。 struts2 中 String intercept(ActionInvocation invocation)就相当于Filter中的doFilter方法。
2)原理
Struts 2的拦截器实现相对简单。当请求到达Struts2的ServletDispatcher时,Struts 2会查找配置文件,并根据其配置实例化相对的拦截器对象,然后串成一个列表(list),最后一个一个地调用列表中的拦截器。事实上,我们之所以能够如此 灵活地使用拦截器,完全归功于“动态代理”的使用。动态代理是代理对象根据客户的需求做出不同的处理。对于客户来说,只要知道一个代理对象就行了。
那Struts2中,拦截器是如何通过动态代理被调用的呢?当Action请求到来的时候,会由系统的代理生成一个Action的代理对象,由 这个代理对象调用Action的execute()或指定的方法,并在struts.xml中查找与该Action对应的拦截器。如果有对应的拦截器,就 在Action的方法执行前(后)调用这些拦截器;如果没有对应的拦截器则执行Action的方法。其中系统对于拦截器的调用,是通过 ActionInvocation来实现的。代码如下:
if (intexrceptors.hasNet()) {Interceptor interceptor=(Interceptor)interceptors.next();resultCode = interceptor.intercept(this);} else {if (proxy.getConfig().getMethodName() == null) {resultCode = getAction().execute();} else {resultCode = invokeAction(getAction(), proxy.getConfig());}}
3、原理的实现模拟过程
1)拦截器接口
public interface MyInterceptor { public void inteceptor(Invocation invocation) ; } <span style="font-size:18px;"><span style="font-size:12pt"> </span></span>
2)拦截器两个实现类
<span style="font-size:18px;">public class FirstInterceptor implements MyInterceptor { public void inteceptor(Invocation invocation) { System.out.println("第一个拦截器开始。。。。"); //调用invoke方法 invocation.invoke() ; System.out.println("第一个拦截器结束......."); } } public class SecondInterceptor implements MyInterceptor { public void inteceptor(Invocation invocation) { System.out.println("第二个拦截器开始....."); //调用invoke方法 invocation.invoke() ; System.out.println("第二个拦截器结束......"); } }<span style="font-size:12pt"> </span></span>
3)Action
<span style="font-size:18px;">public class Action { public String execute() { System.out.println("执行execute方法"); return null ; } }</span>
4)控制器
<span style="font-size:18px;">public class Invocation { List<MyInterceptor> interceptors = new ArrayList<MyInterceptor>(); int index = -1; public Invocation() { //需要执行的拦截器 this.interceptors.add(new FirstInterceptor()); this.interceptors.add(new SecondInterceptor()); } public void invoke() { index++; if (index < interceptors.size()) { //一次调用拦截器的inteceptor方法 interceptors.get(index).inteceptor(this); } else { //拦截器拦截完毕后执行action new Action().execute(); } } } </span>
5)拦截器入口
<span style="font-size:18px;"> public static void main(String[] args) { //struts2的拦截器入口就是invoke方法 new Invocation().invoke() ; }</span>