Strut2的工作原理
图中我们可以看到一个原始请求通过一系列的标准过滤器链传递给Servlet容器,这些过滤器包括ActionContextCleanUp过滤器(可选的,Struts 2.1.3之后的版本均不需要配置该过滤器,下文会对 这个过滤器作进一步解释)还有如SiteMesh等其他过滤器。
接下来调用核心控制器FilterDispatcher,它将调用ActionMapper去确定该请求将触发哪个action。一旦 ActionMapper确定了调用的action,核心控制器FilterDispatcher会将控制权委托给ActionProxy,由它调用配置 管理器从配置文件中读取配置信息(这些配置信息可以从struts.xml中获取),然后创建ActionInvocation对象,该对象持有拦截器和 对应的Action实例,它将在调用Action之前执行完所有的拦截器。
当Action返回执行结 果,ActionInvocation将会从struts.xml的配置信息中查找与Action-result-code相匹配的result。接着执 行相应的result,这通常(在有action链的情况下并不会)会触发一些用jsp或者freemarker写的页面模板。其他的一些组件可能会通过 ActionMapper返回相应的URL作为额外的请求。
在HttpServletResponse返回之前,拦截器会被再次执行(反序调用),最后,响应response通过在web.xml中配置的f过滤器返回给请求者。
若ActionContextCleanUp过滤器还是活跃的,核心控制器FilterDispatcher将不清除ActionContext,否则清之。
2、ActionContextCleanUp的作用
延长action中属性的生命周期,包括自定义属性,以便在jsp页面中进行访问,让actionContextcleanup过滤器来清除属性,不让action自己清除。为了使用WebWork,我们只需要在web.xml配置FilterDispatcher一个过滤器即可。
在ActionContextCleanUp中,有这样的代码:
req.setAttribute(CLEANUP_PRESENT, Boolean.TRUE);
如果FilterDispatcher检测到这个属性,就不会清除ActionContext中的内容了,而由ActionContextCleanUp后续的代码来清除,保证了一系列的Filter访问正确的ActionContext.如果用到SiteMesh的Filter或者其他类似Filter,那么设置顺序是:
ActionContextCleanUp filter
SiteMesh filter
FilterDispatcher
就是说,一般情况下,如果你要用SiteMesh或者其他过滤器,一般是放在FilterDispatcher或者是现在的StrutsPrepareAndExecuteFilter之前。在调用完所有过滤器的doFilter方法后,核心过滤器FilterDispatcher或者StrutsPrepareAndExecuteFilter会清空ActionContext,如果其他过滤器要一直使用value stack等struts的特性时,如果不用ActionContextCleanUp的话,便得不到想要的值。
Deprecated. Since Struts 2.1.3, use StrutsPrepareFilter and StrutsExecuteFilter to use other Servlet filters that need access to the ActionContext
3、FilterDispatcher与StrutsPrepareAndExecuteFilter过滤器
1)FilterDispatcher
Struts2的API文档中显示:Deprecated. Since Struts 2.1.3, use StrutsPrepareAndExecuteFilter instead or
StrutsPrepareFilter and StrutsExecuteFilter if needing using the ActionContextCleanUp filter in addition to this one
由于该FilteDispatcherr已经Deprecated,这里就不对其作更深的探讨。它的主要功能如下:
(1)执行Actions
(2)清除ActionContext
(3)维护静态内容
(4)清除request生命周期内的XWork的interceptors
另注:该过滤器应该过滤所有的请求URL。一般被设置为/*.
2)StrutsPrepareAndExecuteFilter
FilterDispatcher是struts2.0.x到2.1.2版本的核心过滤器!StrutsPrepareAndExecuteFilter是自2.1.3开始就替代了FilterDispatcher的。
StrutsPrepareAndExecuteFilter与普通的Filter并无区别,方法除继承自Filter外,仅有一个回调方法,有兴趣的可以查看其实现代码。
StrutsPrepareAndExecuteFilter的prepare与execute,前者表示准备,可以说是指filter中的init方法,即配制的导入;后者表示进行过滤,指doFilter方法,即将request请求,转发给对应的 action去处理。
StrutsPrepareAndExecuteFilter过滤器中包含相应的功能。
三个初始化参数:
1、config参数:指定要加载的配置文件。逗号分割。
2、actionPackages参数:指定Action类所在的包空间,逗号分割。
3、configProviders参数:自定义配置文件提供者,需要实现ConfigurationProvider接口类,逗号分割。
4、ActionContext
在Struts2开发中,除了将请求参数自动设置到Action的字段中,我们往往也需要在Action里直接获取请求(Request)或会话(Session)的一些信息,甚至需要直接对JavaServlet Http的请求(HttpServletRequest),响应(HttpServletResponse)操作. 我们需要在Action中取得request请求参数"username"的值:
ActionContext context = ActionContext.getContext();
Map params = context.getParameters();
String username = (String) params.get("username");
ActionContext(com.opensymphony.xwork.ActionContext)是Action执行时的上下文,上下文可以看作是一个容器(其实我们这里的容器就是一个Map而已),它存放的是Action在执行时需要用到的对象. 一般情况, 我们的ActionContext都是通过: ActionContext context = (ActionContext) actionContext.get();来获取的.
我们再来看看这里的actionContext对象的创建: static ThreadLocal actionContext = new ActionContextThreadLocal();
ActionContextThreadLocal是实现ThreadLocal的一个内部类.ThreadLocal可以命名为"线程局部变量",它为每一个使用该变量的线程都提供一个变量值的副本,使每一个线程都可以独立地改变自己的副本,而不会和其它线程的副本冲突.这样,我们ActionContext里的属性只会在对应的当前请求线程中可见,从而保证它是线程安全的.
通过ActionContext取得HttpSession: Map session = ActionContext.getContext().getSession();