shuiluobu 2010-10-23
记得一次面试当面试官问起我有关struts2是如何把参数直接封装到action的属性当中的。在那一秒我竟然想不起struts到底是如果做到的,只知道它做到了。很多时候我们在写代码,只是在为了功能而去写,去用到一些工具,然后按照配置,按照套路,一步一步的去走,可以实现,有时候可能大概的知道可能是如何如何实现的。却很少去真正的弄清楚。当面试完了,突然我想起来,struts2之所以可以有那么神奇,只是因为他有强大的一组Interceptor在帮着做一些我们不用关心的事!
google一下,可以发现struts2的核心就是Interceptor。但是拦截器,到底是怎么样可以实现那么多神奇的效果和功能的呢?
其实,Interceptor就是一个aop,也许只是在spring当中听到aop比较多,却不知道aop是几乎很多开源框架都会用到的模式。而aop那么神奇有到底怎么样可以在一个方法执行前,执行后,拦截到的呢。
其实,aop的实现就是动态代理。我的理解就是代理模式+反射。在运行时真正执行并不是我写的那些action而是struts的action代理。如果想了解动态代理,我的博客里有一篇java动态代理机制分析,文章来自ibm的大牛,解析的很全面。
下面回到struts的拦截器,贴一张struts2的工作机制图
从图可以看出,一个请求在Struts2框架中的处理大概分为以下几个步骤:
1、客户端初始化一个指向Servlet容器(例如Tomcat)的请求;
2、这个请求经过一系列的过滤器(Filter)(这些过滤器中有一个叫ActionContextCleanUp的可选过滤器,这个过滤器对于Struts2和其他框架的集成很有帮助,例如:SiteMeshPlugin);
3、接着FilterDispatcher被调用,FilterDispatcher询问ActionMapper来决定这个请求是否需要调用某个Action;
4、如果ActionMapper决定需要调用某个Action,FilterDispatcher把请求的处理交给ActionProxy;
5、ActionProxy通过ConfigurationManager询问框架的配置文件,找到需要调用的Action类;
6、ActionProxy创建一个ActionInvocation的实例。
7、ActionInvocation实例使用命名模式来调用,在调用Action的过程前后,涉及到相关拦截器(Intercepter)的调用。
8、一旦Action执行完毕,ActionInvocation负责根据struts.xml中的配置找到对应的返回结果。返回结果通常是(但不总是,也可能是另外的一个Action链)一个需要被表示的JSP或者FreeMarker的模版。在表示的过程中可以使用Struts2框架中继承的标签。在这个过程中需要涉及到ActionMapper。
注:以上步骤参考至网上,具体网址已忘记。在此表示感谢!
下面我引用了一些默认拦截器的简单说明;有兴趣可以看下源代码,源码就不贴了。
拦截器
名字
说明
AliasInterceptor
alias
在不同请求之间将请求参数在不同名字件转换,请求内容不变
ChainingInterceptor
chain
让前一个Action的属性可以被后一个Action访问,现在和chain类型的result(<resulttype=”chain”>)结合使用。
CheckboxInterceptor
checkbox
添加了checkbox自动处理代码,将没有选中的checkbox的内容设定为false,而html默认情况下不提交没有选中的checkbox。
CookiesInterceptor
cookies
使用配置的name,value来是指cookies
ConversionErrorInterceptor
conversionError
将错误从ActionContext中添加到Action的属性字段中。
CreateSessionInterceptor
createSession
自动的创建HttpSession,用来为需要使用到HttpSession的拦截器服务。
DebuggingInterceptor
debugging
提供不同的调试用的页面来展现内部的数据状况。
ExecuteandWaitInterceptor
execAndWait
在后台执行Action,同时将用户带到一个中间的等待页面。
ExceptionInterceptor
exception
将异常定位到一个画面
FileUploadInterceptor
fileUpload
提供文件上传功能
I18nInterceptor
i18n
记录用户选择的locale
LoggerInterceptor
logger
输出Action的名字
MessageStoreInterceptor
store
存储或者访问实现ValidationAware接口的Action类出现的消息,错误,字段错误等。
ModelDrivenInterceptor
model-driven
如果一个类实现了ModelDriven,将getModel得到的结果放在ValueStack中。
ScopedModelDriven
scoped-model-driven
如果一个Action实现了ScopedModelDriven,则这个拦截器会从相应的Scope中取出model调用Action的setModel方法将其放入Action内部。
ParametersInterceptor
params
将请求中的参数设置到Action中去。
PrepareInterceptor
prepare
如果Acton实现了Preparable,则该拦截器调用Action类的prepare方法。
ScopeInterceptor
scope
将Action状态存入session和application的简单方法。
ServletConfigInterceptor
servletConfig
提供访问HttpServletRequest和HttpServletResponse的方法,以Map的方式访问。
StaticParametersInterceptor
staticParams
从struts.xml文件中将<action>中的<param>中的内容设置到对应的Action中。
RolesInterceptor
roles
确定用户是否具有JAAS指定的Role,否则不予执行。
TimerInterceptor
timer
输出Action执行的时间
TokenInterceptor
token
通过Token来避免双击
TokenSessionInterceptor
tokenSession
和TokenInterceptor一样,不过双击的时候把请求的数据存储在Session中
ValidationInterceptor
validation
使用action-validation.xml文件中定义的内容校验提交的数据。
WorkflowInterceptor
workflow
调用Action的validate方法,一旦有错误返回,重新定位到INPUT画面
ParameterFilterInterceptor
N/A
从参数列表中删除不必要的参数
ProfilingInterceptor
profiling
通过参数激活profi
-----------------------------------------------
关于struts拦截器,还有自定义拦截器,相信都有一些了解,和应用,google一下,很多实例。也就不重复贴了。