Struts2学习笔记之Context Map

来源:互联网 发布:探测网络拓扑 编辑:程序博客网 时间:2024/05/17 12:52


    在Struts2中,动作类是多例的,每次访问action,动作类都会实例化,所以线程是安全的(这样也是与Struts1的区别,Struts1中的动作类是单例的)。

    必须要思考一个问题,每次请求的数据存放究竟是如何承载的的?这是我写下这篇博客的主要目的。

    参见官方文档中,有这样的描述:

The framework sets the OGNL context to be our ActionContext, and the value stack to be the OGNL root object.(The value stack is a set of several objects, but to OGNL it appears to be a single object.) Along with the value stack, the framework places other objects in the ActionContext,including Maps representing the application, session, and request contexts. These objects coexist in the ActionContext, alongside the value stack (our OGNL root).
        OGNL(the Object Graph Navigation Language,这里不再赘述),是由ActionContext作为上下文和valuestack作为根对象。

    |                     |--application                     |                     |--session       context map---|                     |--value stack(root)                     |                     |--action (the current action)                     |                     |--request                     |                     |--parameters                     |                     |--attr (searches page, request, session, then application scopes)                     |

    由此可见,请求的数据是由其二者(ActionContext、ValueStack)共同承载的。

  contextMap中存放的主要内容

Key

Value

说明

value stack (root)

java.util.List

没有root这个key。它是一个list

application

java.util.Map<String,Object>

ServletContext中的所有属性。

session

java.util.Map<String,Object>

HttpSession中的所有属性。

request

java.util.Map<String,Object>

ServletRequest中的所有属性。

parameters

java.util.Map

参数

attr

java.util.Map

把页面、请求、会话、应用范围内的所有属性放到一起。


    有一点是可以明确的,在每次动作执行前,核心过滤器StrutsPrepareAndExecuteFilter都会创建一个ActionContext和ValueStack对象。且每次动作访问都会创建。这两个对象存储了整个动作访问期间用到的数据

    由ActionContex源码中的这段:

static ThreadLocal<ActionContext> actionContext = new ThreadLocal<ActionContext>();

     可见其把数据绑定到线程局部变量(ThreadLoacl)上了。所以是线程安全的。

    我们追溯其源码,ActionContext的构造方法

  private Map<String, Object> context;    /**     * Creates a new ActionContext initialized with another context.     *     * @param context a context map.     */    public ActionContext(Map<String, Object> context) {        this.context = context;    }

   其本质就是一个Map。再看valueStack

  /**     * Get the CompoundRoot which holds the objects pushed onto the stack     *     * @return the root     */    public abstract CompoundRoot getRoot();

    追溯compoundRoot可见:

public class CompoundRoot extends ArrayList { //继承自Arraylist,其自增长的数组的数据结构    public CompoundRoot() {    }    public CompoundRoot(List list) {        super(list);    }    public CompoundRoot cutStack(int index) {        return new CompoundRoot(subList(index, size()));//截取list,并使用截取下的新list创建一个新的root    }    public Object peek() {        return get(0);    }    public Object pop() {        return remove(0);    }    public void push(Object o) {        add(0, o);    }}

           valueStack的本质,就是一个List。

    可以得出结论,除了value stack之外,全是map,而contextMap也是一个map。其实就是Map中又封装的Map。(很像dbutils中KeyedHandler封装数据的结构,只是封装数据的结构)。


0 0
原创粉丝点击