值栈(ValueStack)是什么?

值栈(ValueStack)就是 OGNL 表达式存取数据的地方。在一个值栈中,封装了一次请求所需要的所有数据。

在使用 Struts2 的项目中,Struts2 会为每个请求创建一个新的值栈,也就是说,值栈和请求是一一对应的关系,这种一一对应的关系使值栈能够线程安全地为每个请求提供公共的数据存取服务。

1. 值栈的作用

值栈可以作为一个数据中转站在前台与后台之间传递数据,最常见的就是将 Struts2 的标签与 OGNL 表达式结合使用。值栈实际上是一个接口,在 Struts2 中利用 OGNL 时,实际上使用的就是实现了该接口的 OgnlValueStack 类,这个类是 OGNL 的基础。

2. 值栈的生命周期

值栈贯穿整个 Action 的生命周期,每个 Action 类的对象实例都拥有一个 ValueStack 对象,在 ValueStack 对象中保存了当前 Action 对象和其他相关对象。

Struts2 框架把 ValueStack 对象保存在一个名为 struts.valueStack 的 request 属性中,也就是说,值栈与 Action 的生命周期一致。值栈的生命周期随着 request 的创建而创建,随着 request 的销毁而销毁。

3. 值栈的获取方式

要获取值栈中存储的数据,首先应该获取值栈。值栈的获取有两种方式,具体如下。

1)在 request 中获取值栈

ValueStack 对象在 request 范围内的存储方式为 request.setAttribute("struts.valueStack",valuestack),可以通过如下方式从 request 中取出值栈的信息。

//获取 ValueStack 对象,通过 request 对象获取
ValueStack valueStack = (ValueStack)ServletActionContext.getRequest()
            .getAttribute(ServletActionContext.STRUTS_VALUESTACK_KEY);

在上述示例代码中,ServletActionContext.STRUTS_VALUESTACK_KEY 是 ServletActionContext 类中的常量,它的值为 struts.valueStack。

2)在 ActionContext 中获取值栈

在使用 Struts2 框架时,可以使用 OGNL 操作 Context 对象从 ValueStack 中存取数据,也就是说,可以从 Context 对象中获取 ValueStack 对象。实际上,Struts2 框架中的 Context 对象就是 ActionContext。

ActionContext 获取 ValueStack 对象的方式如下所示:

//通过 ActionContext 获取 valueStack 对象
ValueStack valueStack = ActionContext.getContext().getValueStack();

ActionContext 对象是在 StrutsPrepareAndExcuteFilter 的 doFilter() 方法中被创建的,在源码中用于创建 ActionContext 对象的 createActionContext() 方法内可以找到获取的 ValueStack 对象的信息。

方法中还有这样一段代码:

ctx=new ActionContext(stack.getContext());

从上述代码中可以看出,ValueStack 对象中的 Context 对象被作为参数传递给了 ActionContext 对象,这也就说明 ActionContext 对象中持有了 ValueStack 对象的引用,因此可以通过 ActionContext 对象获取 ValueStack 对象。