Struts2值栈ValueStack介绍

来源:互联网 发布:西门子博图软件 编辑:程序博客网 时间:2024/05/21 00:47

ValueStack(值栈): 贯穿整个 Action 的生命周期(每个 Action 类的对象实例都拥有一个ValueStack对象,每次请求都会创建一个Action类)。请求完成后ValueStack与request将一起消失。

ValueStack相当于一个数据的中转站. 在其中保存当前Action 对象和其他相关对象.

ValueStack实际是一个接口,在Struts2中利用OGNL时,实际上使用的是实现了该接口的OgnlValueStack类,这个类是Struts2利用OGNL的基础

Struts框架把ValueStack对象保存在名为“struts.valueStack” 的请求属性中,request中ServletActionContext类中提供了一个常量
public static final String STRUTS_VALUESTACK_KEY = “struts.valueStack”;

值栈的获取:

//获取方式一ValueStack valueStack = ActionContext.getContext().getValueStack();//获取方式二ValueStack valueStack2 = (ValueStack) ServletActionContext.getRequest().getAttribute("struts.valueStack");

在 ValueStack 对象的内部有两个逻辑部分:
ObjectStack: Struts把动作和相关对象压入ObjectStack中,底层实现对象为CompoundRoot, CompoundRoot是一个ArrayList
ContextMap: Struts 把各种各样的映射关系(一些 Map 类型的对象) 压入 ContextMap 中。底层为Map

对值栈的操作,默认都是Root对象的操作,访问数据时不需要使用#号
Struts 会把下面这些映射压入 ContextMap 中,获取时间是需要使用#号
parameters: 该 Map 中包含当前请求的请求参数
request: 该 Map 中包含当前 request 对象中的所有属性
session: 该 Map 中包含当前 session 对象中的所有属性
application:该 Map 中包含当前 application 对象中的所有属性
attr: 该 Map 按如下顺序来检索某个属性: request, session, application

ValueStack内部底层图解分析:
这里写图片描述

OgnlValueStack 类包含两个重要的属性:一个root和一个context。
其中root本质上是一个ArrayList.
而context 是一个Map(更确切的说是一个OgnlContext对象)
在这个OgnlContext对象(context)中,有一个默认的顶层对象_root,OGNL访问context中这个默认顶层对象中的元素时,是不需要#号的,直接通过元素的名称来进行访问,而访问其他对象时,如 request、session、attr等,则需要#号引用。

Struts2将OgnlValueStack的root对象赋值给了OgnlContext中的_root对象,在OgnlValueStack的root对象中,保存着调用Action的实例,因此,在页面上通过Struts2标签访问Action 的属性时,就不需要通过#号来引用

总结:ognl Context包含 ObjectStack属性和ContextMap属性

当Struts2接受一个请求时,会迅速创建ActionContext,ValueStack,action 。然后把action存放进ValueStack,所以action的实例变量可以被OGNL访问。

ServletActionContext.getRequest()                       .setAttribute("username", "username_request");ServletActionContext.getContext().getSession()                       .put("username", "username_session");ServletActionContext.getServletContext()                       .setAttribute("username", "username_application");ActionContext提供了对ognl上下文对象中数据操作的方法.valueStack = ServletActionContext.getContext().getValueStack();valueStack.set("username", "username_valueStack");valueStack.push(new User("u001", "zhangsan", "12345"));

值栈的使用示例:
action类:

package com.my.action;import com.my.bean.User;import com.opensymphony.xwork2.ActionContext;import com.opensymphony.xwork2.ActionSupport;import com.opensymphony.xwork2.ModelDriven;import com.opensymphony.xwork2.util.ValueStack;public class ValueStackAction extends ActionSupport implements ModelDriven<User> {    private User user = new User();    @Override    public String execute() throws Exception {        //获得值栈        ValueStack valueStack = ActionContext.getContext().getValueStack();        // 给context 存放数据        ActionContext.getContext().put("ac", "request_ValueStack"); //给Map栈中存放数据        ActionContext.getContext().getSession().put("ac", "session_ValueStack"); //将数据存放在context Map中 key为session ,value = entry(key = value)        ActionContext.getContext().getApplication().put("ac", "application_ValueStack");        // 将栈顶的数据弹出        // valueStack.pop();        User user = new User(); //查询结果        user.setUsername("zhangsan");        user.setPassword("1234");        this.user = user;        return SUCCESS;    }    @Override    public User getModel() {        return this.user ;    }}

action配置:

<action name="valueStackAction" class="com.my.action.ValueStackAction">            <result name="success">/success.jsp</result>        </action>

valueStack.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"    pageEncoding="UTF-8"%><!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"><html><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8"><title>Insert title here</title></head><body>    <form action="${pageContext.request.contextPath}/valueStackAction" method="post">        用户名:<input type="text" name="username" /> <br/>        密码:<input type="text" name="password" /> <br/>        <input type="submit" value="提交" />    </form></body></html>

success.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"    pageEncoding="UTF-8"%><%@ taglib uri="/struts-tags" prefix="s"%><!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"><html><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8"><title>Insert title here</title></head><body>  <br/>  <s:debug></s:debug>  <!-- 从context获得数据 -->  <s:property value="#ac"/> <br/>  <s:property value="#session.ac"/> <br/>  <s:property value="#application.ac"/> <br/>  <hr/>  <!-- 使用el获取内容 -->  ${requestScope.ac} <br/>     <!-- struts 对request的getAttribute方法进行增强,先从request获取内容,再从值栈从获取内容 -->  <% request.getAttribute("ac"); %> <br/>  <%=request %> <br/>  <!--  -->   <s:property value="ac"/> <br/> <!-- 先从root栈中获取内容,再从map栈获取内容 -->   ###<s:property value="#request.ac"/> <br/>   <hr/>   <!-- 可以显示表单提交的数据 -->   <s:property value="username"/> <br/>   <s:property value="password"/> <br/>   <!-- Action中执行了valueStack.pop(); -->   <s:property value="model.username"/> <br/>   <s:property value="model.password"/> <br/></body></html>

运行结果:
这里写图片描述

struts2提供了一个<s:debug></s:debug>标签可以对值栈进行详细的显示。
运行结果:
这里写图片描述
这里写图片描述

0 0
原创粉丝点击