Struts2值栈ValueStack介绍详解编程语言

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>标签可以对值栈进行详细的显示。
运行结果:
这里写图片描述
这里写图片描述

原创文章,作者:Maggie-Hunter,如若转载,请注明出处:https://blog.ytso.com/tech/pnotes/12071.html

(0)
上一篇 2021年7月19日 14:18
下一篇 2021年7月19日 14:18

相关推荐

发表回复

登录后才能评论