`

ActionContextCleanUp的作用

 
阅读更多

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

 

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

Java代码 复制代码
  1. String timerKey = "ActionContextCleanUp_doFilter: ";   
  2.   
  3. UtilTimerStack.setActive(true);   
  4.   
  5. UtilTimerStack.push(timerKey);   
  6. //调用要测试的方法。   
  7. UtilTimerStack.pop(timerKey);  
Java代码  收藏代码
  1. String timerKey = "ActionContextCleanUp_doFilter: ";  
  2.   
  3. UtilTimerStack.setActive(true);  
  4.   
  5. UtilTimerStack.push(timerKey);  
  6. //调用要测试的方法。  
  7. UtilTimerStack.pop(timerKey);
分享到:
评论

相关推荐

    robot framework 2.5.30 版本用户手册资料整理 中文版

    Robot Framework user guider资料和使用注意事项,整理资料,主要包括RF的用法和使用注意事项文档资料、测试用例编写、用户关键字定义等

    Struts2整合SiteMesh技巧

    注意ActionContextCleanUp过滤器必须在FilterDispatcher之前配置,ActionContextCleanUp的主要功能是通知FilterDispatcher执行完毕不要清除ActionContext,以便sitemesh装饰器可以访问Struts值堆栈。 配置装饰器 ...

    Struts2源码分析

    Struts2源码分析 请求首先通过Filter chain,Filter 主要包括ActionContextCleanUp,它主要清理当前线 程的ActionContext 和Dispatcher;FilterDispatcher 主要通过AcionMapper 来决定需要调用哪 个Action。

    struts PPT讲解

    工作流程当接收到一个httprequest  Interceptor做一些拦截或者初始的工作  当外部的httpservletrequest到来时  初始到了servlet容器 传递给一个标准的过滤器链  ActionContextCleanUp这个在集成插件方面非常有

    Struts2的工作原理和流程

    2 这个请求经过一系列的过滤器(Filter)(这些过滤器中有一个叫做ActionContextCleanUp的可选过滤器,这个过滤器对于Struts2和其他框架的集成很有帮助,例如:SiteMesh Plugin) 3 接着FilterDispatcher被调用,...

    struts2开发文档

    ActionContextCleanUp的可选过滤器,这个过滤器对于Struts2和其他框 架的集成很有帮助,例如:SiteMesh Plugin) 3 接着FilterDispatcher被调用,FilterDispatcher询问ActionMapper来 决定这个请是否需要调用某个...

    解决struts2.1.6+spring+hibernate 中文乱码

    struts.properties设置( struts.objectFactory = spring struts.i18n.reload=true ... org.apache.struts2.dispatcher.ActionContextCleanUp &lt;filter-name&gt;struts-cleanup &lt;url-pattern&gt;/* &lt;/filter-mapping&gt;

    Java Struts 实现拦截器

    • 客户端产生一个HttpServletRequest的请求,该请求被提交到一系列的标准过滤器(Filter)组建链中(如ActionContextCleanUp:它主要是清理当前线程的ActionContext、Dispatcher,FilterDispatcher主要是通过...

    struts2流程与流程图

     请求被提交到一系列(主要是3层)的过滤器(Filter),如(ActionContextCleanUp、其他过滤器(SiteMesh等)、 FilterDispatcher)。注意:这里是有顺序的,先ActionContext CleanUp,再其他过滤器(Othter ...

    java中文乱码解决方案

    -- zh-cn encoding --&gt; &lt;filter&gt; &lt;filter-name&gt;struts-cleanup &lt;/filter-name&gt; &lt;filter-class&gt; org.apache.struts2.dispatcher.ActionContextCleanUp &lt;/filter-class&gt; &lt;/filter&gt; ...

    SSH的jar包.rar

    2、这个请求经过一系列的过滤器(Filter)(这些过滤器中有一个叫做ActionContextCleanUp的可选过滤器,这个过滤器对于Struts2和其他框架的集成很有帮助,例如:SiteMesh Plugin) 3、接着FilterDispatcher被调用,...

    Struts2请求处理流程及源码分析

    b)根据Web.xml配置,请求首先经过ActionContextCleanUp过滤器,其为可选过滤器,这个过滤器对于Struts2和其他框架的集成很有帮助(SiteMeshPlugin),主要清理当前线程的ActionContext和Dispatcher;c)请求经过插件...

    解决struts2下载异常的jar包 struts2-sunspoter-stream-1.0.jar

    235) at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206) at org.apache.struts2.dispatcher.ActionContextCleanUp.doFilter(ActionContextCleanUp.java:102) at org....

Global site tag (gtag.js) - Google Analytics