延长action中属性的生命周期,包括自定义属性,以便在jsp页面中进行访问,让actionContextcleanup过滤器来清除属性,不让action自己清除。

为了使用WebWork,我们只需要在web.xml配置FilterDispatcher一个过滤器即可,阅读一下FilterDispatcher的JavaDoc和源码,我们可以看到它调用了:

finally
 {
            ActionContextCleanUp.cleanUp(req);
 }

在ActionContextCleanUp中,有这样的代码:

req.setAttribute(CLEANUP_PRESENT, Boolean.TRUE);

如果FilterDispatcher检测到这个属性,就不会清除ActionContext中的内容了,而由ActionContextCleanUp后续的代码来清除,保证了一系列的Filter访问正确的ActionContext.

文档中提到,如果用到SiteMesh的Filter或者其他类似Filter,那么设置顺序是:

ActionContextCleanUp filter
 SiteMesh filter
 FilterDispatcher
 所以最后我们的web.xml应该类似这样:

<filter>
        <filter-name>ActionContextCleanUp</filter-name>
        <filter-class>com.opensymphony.webwork.dispatcher.ActionContextCleanUp</filter-class>
    </filter>

<filter>
        <filter-name>sitemesh</filter-name>
        <filter-class>com.opensymphony.webwork.sitemesh.FreeMarkerPageFilter</filter-class>
    </filter>

<filter>
        <filter-name>webwork</filter-name>
        <filter-class>com.opensymphony.webwork.dispatcher.FilterDispatcher</filter-class>
    </filter>

<filter-mapping>
        <filter-name>ActionContextCleanUp</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>

<filter-mapping>
        <filter-name>sitemesh</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>

<filter-mapping>
        <filter-name>webwork</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>

---------------------------------------------------------------------------------------------------------------------

在Struts 2.1.6之前,ActionContextCleanUp的完整路径是com.opensymphony.webwork.dispatcher.ActionContextCleanUp,现在的路径变成了org.apache.struts2.dispatcher.ActionContextCleanup。

那么这个类究竟有什么用处呢?是不是一定要用呢?

下面是这个类内部的注释。

Special filter designed to work with the FilterDispatcher and allow
for easier integration with SiteMesh. Normally, ordering your filters to have
SiteMesh go first, and then FilterDispatcher go second is perfectly fine.
However, sometimes you may wish to access Struts features, including the
value stack, from within your SiteMesh decorators. Because FilterDispatcher
cleans up the ActionContext, your decorator won't have access to the
data you want.
     By adding this filter, the FilterDispatcher will know to not clean up and
instead defer cleanup to this filter. The ordering of the filters should then be:
1.this filter

2.SiteMesh filter

3.FilterDispatcher

就是说,一般情况下,如果你要用SiteMesh或者其他过滤器,一般是放在FilterDispatcher或者是现在的StrutsPrepareAndExecuteFilter之前。在调用完所有过滤器的doFilter方法后,核心过滤器FilterDispatcher或者StrutsPrepareAndExecuteFilter会清空ActionContext,如果其他过滤器要一直使用value stack等struts的特性时,如果不用ActionContextCleanUp的话,便得不到想要的值。

ActionContextCleanUp 的作用就是上面用粗体标注出来的那一句。它会在doFilter方法里设置一个计数器counter的初始值为1,有了这个值,后续的核心过滤器就不会清 空ActionContext,而是由之前的过滤器也就是ActionContextCleanUp来清空ActionContext。

------------------------------------------------------------------------------------------------------------------------------------------------------

 

1. ActionContext

ActionContext是被存放在当前线程中的,获取ActionContext也是从ThreadLocal中获取的。所以在执行拦截器、 action和result的过程中,由于他们都是在一个线程中按照顺序执行的,所以可以可以在任意时候在ThreadLocal中获取 ActionContext。

ActionContext包括了很多信息,比如Session、Application、Request、Locale、ValueStack等,其中 ValueStack可以解析ognl表达式,来动态获取一些值,同时可以给表达式提供对象。

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(); (通过Map模拟HttpServlet的对象,操作更方便)

2. ServletActionContext

ServletActionContext(com.opensymphony.webwork. ServletActionContext),这个类直接继承了我们上面介绍的ActionContext,它提供了直接与Servlet相关对象访问的 功能,它可以取得的对象有:

(1)javax.servlet.http.HttpServletRequest : HTTPservlet请求对象 
(2)javax.servlet.http.HttpServletResponse : HTTPservlet相应对象 
(3)javax.servlet.ServletContext : Servlet上下文信息 
(4)javax.servlet.ServletConfig : Servlet配置对象 
(5)javax.servlet.jsp.PageContext : Http页面上下文

如何从ServletActionContext里取得Servlet的相关对象:

<1>取得HttpServletRequest对象: HttpServletRequest request = ServletActionContext. getRequest();

<2>取得HttpSession对象: HttpSession session = ServletActionContext. getRequest().getSession();

3. ServletActionContext和ActionContext联系

ServletActionContext和ActionContext有着一些重复的功能,在我们的Action中,该如何去抉择呢?我们遵循的原则 是:如果ActionContext能够实现我们的功能,那最好就不要使用ServletActionContext,让我们的Action尽量不要直接 去访问Servlet的相关对象.

注意:在使用ActionContext时有一点要注意: 不要在Action的构造函数里使用ActionContext.getContext(), 因为这个时候ActionContext里的一些值也许没有设置,这时通过ActionContext取得的值也许是null;同 样,HttpServletRequest req = ServletActionContext.getRequest()也不要放在构造函数中,也不要直接将req作为类变量给其赋值。 至于原因,我想是因为前面讲到的static ThreadLocal actionContext = new ActionContextThreadLocal(),从这里我们可以看出ActionContext是线程安全的,而 ServletActionContext继承自ActionContext,所以ServletActionContext也线程安全,线程安全要求每 个线程都独立进行,所以req的创建也要求独立进行,所以ServletActionContext.getRequest()这句话不要放在构造函数 中,也不要直接放在类中,而应该放在每个具体的方法体中(eg:login()、queryAll()、insert()等),这样才能保证每次产生对象 时独立的建立了一个req。

4.ActionContextClearUp

ActionContextClearUp其实是Defer ClearUP.作用就是延长action中属性的生命周期,包括自定义属性,以便在jsp页面中进行访问,让actionContextcleanup 过滤器来清除属性,不让action自己清除。具体看下面的代码,代码很简单:

Java代码 
  1. public void doFilter(...){
  2. ...
  3. try{
  4. ...
  5. //继续执行所配置的chain中的Filter
  6. chain.doFilter(request, response);
  7. }finally{
  8. //保证在所有动作执行完之后,调用cleanUp
  9. ...
  10. cleanUp(request);
  11. }
  12. }
  13. protected static void cleanUp(ServletRequest req) {
  14. ...
  15. ActionContext.setContext(null);//清除ActionContext实例
  16. Dispatcher.setInstance(null);//清除Dispatcher实例(Dispatcher主要是完成将url解析成对应的Action)
  17. }
Java代码  
  1. public void doFilter(...){
  2. ...
  3. try{
  4. ...
  5. //继续执行所配置的chain中的Filter
  6. chain.doFilter(request, response);
  7. }finally{
  8. //保证在所有动作执行完之后,调用cleanUp
  9. ...
  10. cleanUp(request);
  11. }
  12. }
  13. protected static void cleanUp(ServletRequest req) {
  14. ...
  15. ActionContext.setContext(null);//清除ActionContext实例
  16. Dispatcher.setInstance(null);//清除Dispatcher实例(Dispatcher主要是完成将url解析成对应的Action)
  17. }

另外注明一下UtilTimerStack的push和pop是用来计算调用方法所执行的开始和结束时间,用来做性能测试的。用法如下:

Java代码 
  1. String timerKey = "ActionContextCleanUp_doFilter: ";
  2. UtilTimerStack.setActive(true);
  3. UtilTimerStack.push(timerKey);
  4. //调用要测试的方法。
  5. UtilTimerStack.pop(timerKey);
Java代码  
  1. String timerKey = "ActionContextCleanUp_doFilter: ";
  2. UtilTimerStack.setActive(true);
  3. UtilTimerStack.push(timerKey);
  4. //调用要测试的方法。
  5. UtilTimerStack.pop(timerKey);

ActionContextCleanUp作用的更多相关文章

  1. ActionContextCleanUp

    ActionContextCleanUp作用   延长action中属性的生命周期,包括自定义属性,以便在jsp页面中进行访问,让actionContextcleanup过滤器来清除属性,不让acti ...

  2. struts2框架 转载 精华帖

    一.Struts2简介 参考<JavaEE 轻量级框架应用与开发—S2SH> Struts框架是流行广泛的一个MVC开源实现,而Struts2是Struts框架的新一代产品,是将Strut ...

  3. Struts2 执行流程 以及 Action与Servlet比较 (个人理解)

    上图提供了struts2的执行流程.如下: 1:从客户端发出请求(HTTPServletRequest). 2:请求经过各种过滤器(filter),注:一般情况下,如SiteMesh等其他过滤器要放在 ...

  4. StrutsPrepareAndExecuteFilter的作用

    FilterDispatcher是早期struts2的过滤器,后期的都用StrutsPrepareAndExecuteFilter了,如 2.1.6.2.1.8.StrutsPrepareAndExe ...

  5. Struts2中web.xml里面struts-cleanup作用

    struts2.1.3之后的版本均不需要配置该过滤器 参考: struts-cleanup作用 升级到struts-2.3.14.3之后涉及的改动以及ActionContextCleanUp,Stru ...

  6. if __name__== "__main__" 的意思(作用)python代码复用

    if __name__== "__main__" 的意思(作用)python代码复用 转自:大步's Blog  http://www.dabu.info/if-__-name__ ...

  7. (转载)linux下各个文件夹的作用

    linux下的文件结构,看看每个文件夹都是干吗用的/bin 二进制可执行命令 /dev 设备特殊文件 /etc 系统管理和配置文件 /etc/rc.d 启动的配置文件和脚本 /home 用户主目录的基 ...

  8. github中的watch、star、fork的作用

    [转自:http://www.jianshu.com/p/6c366b53ea41] 在每个 github 项目的右上角,都有三个按钮,分别是 watch.star.fork,但是有些刚开始使用 gi ...

  9. web.xml中welcome-file-list的作用

    今天尝试使用struts2+ urlrewrite+sitemesh部署项目,结果发现welcome-file-list中定义的欢迎页不起作用: <welcome-file-list> & ...

随机推荐

  1. linux比较两个文件的不同(6/21)

    cmp 命令:比较任意两个类型的文件,且吧结果输出到标准输出,默认文件相同不输出,不同的文件输出差异 必要参数 -c 显示不同的信息-l 列出所有的不同信息-s 错误信息不提示 选择参数 -i< ...

  2. pxe-kickstart批量部署文档

    #PXE安装: yum install syslinux xinetd tftp-server httpd -y yum install dhcp -y yum install system-conf ...

  3. C语言中 ln(以自然对数e为底) lg(以十为底) 以及logab(以a为底,b为真数)的相关知识

    总所周知,我们在高中学过对数函数,记作y=logax.下面是百度百科关于对数函数的描述: 对数的定义:一般地,如果ax=N(a>0,且a≠1),那么数x叫做以a为底N的对数,记作x=logaN, ...

  4. uitableview 侧滑删除

    https://github.com/MortimerGoro/MGSwipeTableCell

  5. Effective C++ 条款04:确定对象被使用前已经先被初始化

    规则一 永远在使用对象之前将它初始化 int x = 0; const char* text = "A C-style string"; double d; std:: cin & ...

  6. EF Code-First 学习之旅 级联删除

    级联删除是当删除主记录的时候会自动删除依赖的记录或者设置外键属性为null public class Student { public Student() { } public int Student ...

  7. 使用logrotate做nginx日志分割

    版权申明:转载请注明出处. 文章来源:http://bigdataer.net/?p=266 背景 nginx是一款非常优秀的网络代理工具,但是其日志管理有点缺憾:nginx的access_log会无 ...

  8. spring的几个通知(前置、后置、环绕、异常、最终)

    1.没有异常的 2.有异常的 1.被代理类接口Person.java package com.xiaostudy; /** * @desc 被代理类接口 * * @author xiaostudy * ...

  9. java父类调用被子类重写的方法

    [转][原文]  1.如果父类构造器调用了被子类重写的方法,且通过子类构造函数创建子类对象,调用了这个父类构造器(无论显示还是隐式),就会导致父类在构造时实际上调用的是子类覆盖的方法(你需要了解jav ...

  10. JavaWeb -- Struts2 ResultType细化, 国际化

    1. ResultType细化 <result-types> <result-type name="chain" class="com.opensymp ...