struts拦截器详解
可以说struts中的拦截器是非常重要的了,它做了许多东西,例如
1.静态参数封装
2.动态参数封装
3.Struts2中的很多功能都是由拦截器完成的。比如:servletConfig,staticParam,params,modelDriven等等。
struts2中拦截器与Action的执行调度即执行流程或者说执行顺序是由ActionInvocation来完成的(如果此处不怎么了解可以参看struts2处理请求流程详解) 如图:
下面开始讲一下主菜ActionProxy了.在这之前最好先去了解一下动态Proxy的基本知识.
ActionProxy是Action的一个代理类,也就是说Action的调用是通过ActionProxy实现的,其实就是调用了ActionProxy.execute()方法,而该方法又调用了ActionInvocation.invoke()方法。归根到底,最后调用的是DefaultActionInvocation.invokeAction()方法。
DefaultActionInvocation()->init()->createAction()。
最后通过调用 ActionProxy.exute() --> ActionInvocation.invoke() --> Intercepter.intercept()-->ActionInvocation.invokeActionOnly()-->invokeAction()
ActionInvocation是一接口,struts2其默认实现类是DefaultActionInvocation,拦截器与Action的执行调度就是由该完成,调度逻辑就在该类的invoke方法中,下面是invoke方法核心源码:
public String invoke() throws Exception {
//上面省略很多代码...
//判断是否有下一个拦截器
if (interceptors.hasNext()) {
final InterceptorMapping interceptor = (InterceptorMapping) interceptors.next();//获取拦截器配置
String interceptorMsg = "interceptor: " + interceptor.getName();
UtilTimerStack.push(interceptorMsg);
try {
//执行拦截器的intercept方法
resultCode = interceptor.getInterceptor().intercept(DefaultActionInvocation.this);
}
finally {
UtilTimerStack.pop(interceptorMsg);
}
} else {
//执行Action
resultCode = invokeActionOnly();
}
//下面省略很多代码
return resultCode;
}
finally {
UtilTimerStack.pop(profileKey);
}
}
在DefaultActionInvocation的init方法中完成了对当前正在执行的Action所应用上的拦截器的配置信息,放置在一个名为interceptors的List当中,通过配置信息就能获取相应的拦截器实例并执行其intercept方法,并且把ActionInvocation自已作为输入参数传递进了拦截器的intercept方法,如果在拦截器的intercept方法中又调用了ActionInvocation的invoke方法则又会再次进入invoke方法,只不过这次执行的拦截器是下一个拦截器,依此类推,假设所有拦截器都调用了ActionInvocation的invoke方法,则会把Action所应用上的所有拦截器执行一遍,如果所有拦截器都已执行完成即没有下一个拦截器了,则 if (interceptors.hasNext()) 该if条件不成立就会执行invokeActionOnly()方法,执行完Action各个拦截器依次返回,需要注意的是返回的顺序与执行的顺序刚好相反,后执行的拦截器先执行完成返回,这一点非常重要,这与Filter的执行机制是很类似的。如果不理解可看filter的工作原理(来自 <http://www.cnblogs.com/jinzhengquan/archive/2011/02/16/1955778.html> )所有拦截执行返回后得到一个resultCode去寻找相应的Result进行执行,生成页面。
struts2中所有的拦截器都要实现Interceptor接口,下面看一个其接口声明:
public interface Interceptor extends Serializable {
void destroy();
void init();
String intercept(ActionInvocation invocation) throws Exception;
其中就三个方法,destroy在拦截器销毁的时候会执行,init方法会在拦截器实例化完成后立即执行,最重要的是intercept方法,该方法中执行的逻辑直接影响到整个拦截器的执行流程,如果intercept方法中调用了invocation.invoke()方法则会执行下一个拦截器,如果没有调用而直接返回一个字符串则后面的所有拦截器都不会执行,更不会执行Action,然后该拦截器与前面的拦截器执行返回。
拦截器与Action的执行调度是非常重要的,只有理解了这一点才能更好的理解拦截器的工作原理。
上一篇: Struts2怎么配置登录拦截器
下一篇: [Struts2] 拦截器的配置