Struts2学习之路(8)值栈

本文详细介绍了Struts2框架中的值栈(ValueStack)概念及其内部结构。通过源码解析了OgnlValueStack和CompoundRoot的工作原理,阐述了如何在Action中进行压栈操作及如何在JSP页面上通过OGNL表达式获取值栈中的数据。




Struts2值栈详解
基本介绍
     ValueStack是Struts2的一个接口,字面意义为值栈,OgnlValueStack是 ValueStack的实现类,客 户端发起一个请求,struts2架构会创建一个action实例同时创建一个OgnlValueStack值栈实例, OgnlValueStack贯穿整个Action的生命周期,struts2中使用OGNL将请求Action的参数封装为对象存储 到值栈中,并通过OGNL表达式读取值栈中的对象属性值。

PS:这里先说明一个易混淆的问题,那就是ContextMap和值栈的关系,从广义上来讲,ContextMap中存入了一个值栈的键值对。值栈中又有一个ContextMap的引用,这样就形成了一个互相引用的关系。所以说从广义上来讲,无论是从ContextMap的角度来分析,还是从StackValue的角度来分析,都没问题。有很多文档是以StackValue为起点,逐步分析到ContextMap。不过官方文档,还是以ContextMap作为起点。

值栈的内部结构

OnglValueStack源码

  1. public class OgnlValueStack implements Serializable, ValueStack, ClearableValueStack, MemberAccessValueStack {
  2. CompoundRoot root;
  3. transient Map<String, Object> context;
  4. }

CompoundRoot源码
  1. public class CompoundRoot extends ArrayList {
  2. public CompoundRoot() {
  3. }
  4. public CompoundRoot(List list) {
  5. super(list);
  6. }
  7. public CompoundRoot cutStack(int index) {
  8. return new CompoundRoot(subList(index, size()));
  9. }
  10. public Object peek() {
  11. return get(0);
  12. }
  13. public Object pop() {
  14. return remove(0);
  15. }
  16. public void push(Object o) {
  17. add(0, o);
  18. }
  19. }

由以上源码可以看出,OnglValueStack有两部分,一部分是继承ArrayList实现的一个栈结构,一个就是之前介绍过的,在《ContextMap详解》中介绍过的ContextMap。

关于ContextMap的介绍,这里不再给出,可以参考之前的博客《ContextMap详解》,这里分析下栈结构,也就是CompoundRoot,也就是OGNL三大要素之一的根对象(root),可以参考《ONGL基本使用 》。



CompoundRoot
  • CompoundRoot:存储了action实例,它作为OgnlContext的Root对象。
 
     CompoundRoot继承ArrayList 实现压栈和出栈功能,拥有栈的特点,先进后出,后进先出,最后压进栈的数据在栈顶。
     struts2对原OGNL作出的改进就是Root使用CompoundRoot(自定义栈),使用OnglValueStack
的findValue方法可以在CompoundRoot中从栈顶向栈底查找对象的属性值。
     CompoundRoot作为OgnlContext的Root对象,并且在CompoundRoot中action实例位于栈顶, 当读取achon的属性值时会先从栈顶对象中查找对应的属性,如果找不到则继续查找栈中的其它对象, 如果未找到则到ContextMap中去查找,未找到,则返回null。     

Action
public class ValueStackAction extends ActionSupport{

    /*
     * 获取ValueStack对象,并且可以压栈操作
     * 
     */

    public String Demo1(){
    //获取ActionContext对象
    ActionContext context = ActionContext.getContext();
    //获取ValueStack对象
    ValueStack valueStack = context.getValueStack();
    //压栈操作
    User user = new User();
    user.setName("aa");
    user.setSex("bb");
    //值栈中的key为set*的值,如User中的setName(),则值栈中key为name,而与变量名称无关
    valueStack.push(user);
    return SUCCESS;
    }

}

这里写图片描述

这里写图片描述

jsp

<%@page import="com.opensymphony.xwork2.util.ValueStack"%>
<%@page import="com.opensymphony.xwork2.ActionContext"%>
<%@ 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>

    <!-- 查看ContextMap中的内容 -->
    <s:debug></s:debug>

    <!-- 获取值栈的数据
        使用s:property获取
        获取值栈的数据,直接写属性名称,得到的就是属性的值
        OGML表达式的找法:从栈顶按照属性名称开始找,只要找到之后,就不再往下找
     -->
    姓名:<s:property value="name"/><br>
    性别:<s:property value="sex"/><br>
    <!-- 获取指定位置属性值
            使用的OGNL表达式是:[x].name
        x指的是值栈中对象的索引位置。
     -->
    值栈中第一个name:<s:property value="[0].name"/><br/>
    值栈中第二个name:<s:property value="[1].name"/><br/>

    <!-- 
        当我们使用s:property标签时,没有使用value属性,获取的是栈顶对象。
        当我们不操作值栈时,默认的栈顶对象是:当前执行的动作类
     --> 
     <s:property/>

     <!-- 
         s:property在通过OGNL表达式获取数据时,所调用的方法
         ValueStack的对象中的findValue(String expr) 参数的含义:是一个OGNL表达式
      -->
    <% ActionContext context = ActionContext.getContext();
     ValueStack vs = context.getValueStack();
     Object o1 = vs.findValue("name");
     out.println("name is "+o1);
     out.println("<br/>");
     Object o2 = vs.findValue("[1].name");
     out.println("name1 is "+o2);
     out.println("<br/>");
     Object o3 = vs.findValue("#session.sessionMap3");
     out.println(o3);
     out.println("<br/>");
     Object o4 = vs.findValue("#application.applicationAttr");
     out.println(o4);%>
</body>
</html>
六自由度机械臂ANN人工神经网络设计:正向逆向运动学求解、正向动力学控制、拉格朗日-欧拉法推导逆向动力学方程(Matlab代码实现)内容概要:本文档围绕六自由度机械臂的ANN人工神经网络设计展开,详细介绍了正向与逆向运动学求解、正向动力学控制以及基于拉格朗日-欧拉法推导逆向动力学方程的理论与Matlab代码实现过程。文档还涵盖了PINN物理信息神经网络在微分方程求解、主动噪声控制、天线分析、电动汽车调度、储能优化等多个工程与科研领域的应用案例,并提供了丰富的Matlab/Simulink仿真资源和技术支持方向,体现了其在多学科交叉仿真与优化中的综合性价。; 适合人群:具备一定Matlab编程基础,从事机器人控制、自动化、智能制造、电力系统或相关工程领域研究的科研人员、研究生及工程师。; 使用场景及目标:①掌握六自由度机械臂的运动学与动力学建模方法;②学习人工神经网络在复杂非线性系统控制中的应用;③借助Matlab实现动力学方程推导与仿真验证;④拓展至路径规划、优化调度、信号处理等相关课题的研究与复现。; 阅读建议:建议按目录顺序系统学习,重点关注机械臂建模与神经网络控制部分的代码实现,结合提供的网盘资源进行实践操作,并参考文中列举的优化算法与仿真方法拓展自身研究思路。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值