理解ValueStack的基本机制!对各种现象作出解释。

ValueStack实际上就是对OGNL的封装,OGNL主要的功能就是赋值与取值,Struts2正是通过ValueStack来进行赋值与取值的!

ValueStack是一个接口,而OgnlValueStack是strtus2中的缺省实现。ValueStack中的数据,分两个部分存放:root和context(这与OGNL中的概念一致),同时ValueStack暴露相关的接口:

void setValue(String expr, Object value);

Object findValue(String expr);

用来通过OGNL表达式对ValueStack中的数据进行操作!

值栈就是一个List.

ValueStack中的root对象是CompoundRoot,CompoundRoot继承了ArraryList,提供了额外的方法:push()和pop()方法,用来对root对象中所包含的数据进行存取!

public class CompoundRoot extends ArrayList {

public CompoundRoot() {

}

public CompoundRoot(List list) {

super(list);

}

public CompoundRoot cutStack(int index) {

return new CompoundRoot(subList(index, size()));

}

public Object peek() {

return get(0);

}

public Object pop() {

return remove(0);

}

public void push(Object o) {

add(0, o);

}

}

正是通过这两个方法,CompoundRoot变成了一个栈结构!压栈操作,将导致对象被放到CompoundRoot的第0个元素上(第0个元素是栈顶),其它对象被依次往后移动;出栈操作,将导致CompoundRoot的第0个元素被移除(即栈顶元素被弹出),其它对象被依次往前移动!

OGNL不支持多个root对象,而struts2能够支持多个root对象,它对OGNL做了扩展。

如果某个OGNL表达式被传递给ValueStack(即调用ValueStack的setValue或findValue方法),而表达式中包含有对root对象的访问操作,ValueStack将依次从栈顶往栈底搜索CompoundRoot对象中所包含的对象,看哪个对象具有相应的属性,找到之后,立刻返回。

在Struts2中,一个请求在最终到达Action的方法之前,Action对象本身会被压入ValueStack(实际上就是放到ValueStack的CompoundRoot中),所以Action对象是CompoundRoot中的一个元素。看下面的代码:

public class UserAction {

private String username;

private Integer age;

private boolean valid;

//查看用户的详细信息

public String detail(){

username = "张三";

age = 18;

valid = true;

return "detail";

}

在Action中,给Action的username/age/valid赋值。Detail页面如下:

username:<s:property value="username"/> <br/>

valid:<s:property value="valid"/> <br/>

age:<s:property value="age"/> <br/>

上述JSP页面将能正确将它们的值取出。<s:property value=”ognl表达式”/>。在s:property标签中的OGNL表达式,最终会交给ValueStack来解释。username就是一个OGNL表达式,意思是调用root对象的getUsername()方法。Struts2将自动搜索CompoundRoot中有哪些元素(从第0个元素开始搜索),检测这些元素是否有getUsername()方法,如果第0个元素没有getUsername()方法,将继续搜索第1、2、3……个元素是否有getUsername()方法。

在上面的例子中,CompoundRoot中只有一个对象,就是userAction对象,而这个对象中正好有getUsername()方法,所以,上述JSP代码将能够将值正确取出。

再看下面的例子:

public class UserAction {

private String username;

private String name;

//查看用户的详细信息

public String detail(){

username = "张三";

name = "王五";

User u = new User();

u.setUsername("赵毅");

ActionContext.getContext().getValueStack().push(u);

return "detail";

}

在上面这个UserAction的代码中,我们直接调用ActionContext.getContext().getValueStack().push()方法,把一个User对象(这个对象拥有getUsername()和setUsername()方法)直接压入到ValueStack中,这时候,在ValueStack的CompoundRoot中将有两个元素:第0个元素是刚刚压入的user对象[赵毅],而第1个元素是userAction对象[张三],如果在JSP中使用下面的表达式来取值:

<s:property value=”username”/> ,那么输出的值将是“赵毅”!道理上面已经讲过了,struts2将会从第0个元素开始搜索CompoundRoot中的对象,第0个元素正是刚刚压入的那个user对象!

如果在JSP中使用<s:property value=”name”/>来取值,将取出“王五”,因为第0个元素user对象没有name属性,所以,会继续搜索第1个元素userAction对象,在这个对象中就有name属性了!

再看下面的代码:

public class UserAction {

private String username;

//查看用户的详细信息

public String detail(){

username = "张三";

List list = new ArrayList();

for(int i=0; i<10; i++){

User user = new User();

user.setUsername("User"+i);

list.add(user);

}

ActionContext.getContext().put("users", list);

User u = new User();

u.setUsername("赵毅");

ActionContext.getContext().getValueStack().push(u);

return "detail";

}

对应的JSP如下:

1:  <s:property value="username"/> <br/>

2:  <s:iterator value="#users">

3:     <s:property value="username"/>

4:     <s:property value="#root[2].username"/><br/>

5:  </s:iterator>

6:  <s:property value="username"/>

7:  <s:property value="#root[1].username"/> <!-- 张三 -->

根据刚才的示例,我们知道,第1行的username是“赵毅”(因为JSP在执行这行代码的时候,CompoundRoot中有两个元素:第0个是“user对象赵毅”,第1个是“userAction对象张三”),因此第1行的username将取出CompoundRoot中第0个元素的username属性:赵毅

第2行代码是iterator标签,只定义了一个value属性,iterator标签将循环访问users这个List中的User对象,并把当前循环的user对象压入到CompoundRoot中!所以,在第3行和第4行代码被执行的时候,CompoundRoot中总共有3个元素:第0个元素是被iterator标签压入的当前循环的user对象;第1个元素是“user对象赵毅”;第2个元素是“userAction对象张三”,因此第3行代码的执行结果就是输出“UserX”,即当前循环的user对象的username属性!iterator标签将会依次取出List中的user对象,并不断压入/弹出user对象(每次循环,都将执行一遍压入/弹出)。而第4行代码取第2个元素的username属性,即userAction对象的username属性:张三。

第5行代码执行完成之后,在CompoundRoot中将剩下2个元素,与第2行代码被执行之前一样。所以,第6行代码的输出和第1行代码的输出结果是一样的,而第7行代码将取出userAction对象的username属性:张三

应用:ValueStack的更多相关文章

  1. 4. ValueStack 和 OGNL

    1. 属性哪来的 当我们通过Action处理完用户请求以后,可以直接在页面中获取到 action 的属性值. 如果我们在页面中尝试遍历四个域中的属性,会发现域中并没有username之类的Action ...

  2. [转] valuestack,stackContext,ActionContext.之间的关系

    三者之间的关系如下图所示: ActionContext  一次Action调用都会创建一个ActionContext  调用:ActionContext context = ActionContext ...

  3. 什么是ValueStack

    转载自:http://www.cnblogs.com/zyw-205520/archive/2012/09/12/2681346.html Strut2的Action类通过属性可以获得所有相关的值,如 ...

  4. [转]Struts2数据传输的背后机制:ValueStack(值栈)

    1. 数据传输背后机制:ValueStack(值栈) 在这一切的背后,是因为有了ValueStack(值栈)! 2. ValueStack基础:OGNL 要了解ValueStack,必须先理解OGNL ...

  5. OGNL和ValueStack

    OGNL简介 OGNL的全称是Object Graph Navigation Language,即对象导航图语言.它是一个开源项目,工作在视图层,其通过简单一致的表达式语言来读取合适者Java对象的属 ...

  6. OGNl和ValueStack的基础和深入分析

    一.OGNL 1)什么是OGNL? 解析:OGNL是Object Graph Navigation Language(对象图导航语言)它是强大的表达式语言. 2)用途:通过简单一致的表达式语法来读取和 ...

  7. valuestack,stackContext,ActionContext.之间的关系以及如何存取数值的

      2013-03-15 10:54 1722人阅读 评论(1) 收藏 举报  分类: J2EE 版权声明:本文为博主原创文章,未经博主允许不得转载. 三者之间的关系如下图所示: ActionCont ...

  8. Struts 中 ActionContext ctx.put()把数据放到ValueStack里之数据传输背后机制:ValueStack(值栈)

    1.     数据传输背后机制:ValueStack(值栈) 在这一切的背后,是因为有了ValueStack(值栈)! ValueStack基础:OGNL要了解ValueStack,必须先理解OGNL ...

  9. struts2重点——ValueStack和OGNL

    一.值栈(ValueStack) 1.实现类:OGNLValueStack 2.对象栈:CompoundRoot(针对的是类级别的) (1)继承自 ArrayList —— 先进后出 (2)提供了栈的 ...

  10. struts2中valueStack,stackContext以及actionContext的关系

    一,首先给出三者的定义 1.valueStack: 里面存放的是Action类中通过set方法设置的属性值(表单传过来的值等),由OGNL框架实现; 2.stackContext: 也是用来存值的,s ...

随机推荐

  1. vijos1049送给圣诞夜的礼品

    这题犯了两个sb错误,写下来,为以后做个警告 一.mul过程中将k作为了循环变量 二.看错了题…… 题目中说是数到k行,而我却以为数k遍…… 做矩阵乘法,只要记住一句话:置换一定可以写成矩阵的形式! ...

  2. Building QT projects from the command line

    /************************************************************************ * Building QT projects fro ...

  3. (十二)学习CSS之display属性

    参考:http://www.w3school.com.cn/cssref/pr_class_display.asp 浏览器支持 所有主流浏览器都支持 display 属性. 注释:如果规定了 !DOC ...

  4. 内存映射 madvise mmap

    http://linux.die.net/man/2/madvise mmap && madvise的配合使用 mmap和madvise一起使用例子 mmap的作用是将硬盘文件的内容映 ...

  5. 中文Win7下成功安装calabash-android步骤

    Calabash-android是支持android的UI自动化测试框架,网上看见很多同学说,安装calabash比较费劲,特别是Windows下安装,也没有一个详细的安装手册可供参考.正好,今天在W ...

  6. Zabbix探索:网络设备监控2

    在实现第一部分的简单监控的时候,在设置数据类型的时候设置成为了整数,结果: icmpping:这个没问题,只有0和1: icmppingloss:这个有问题,是百分比,其实是浮点数,单位是%: icm ...

  7. JavaScript:子ウィンドウから親ウィンドウを再読み込みさせる方法

    ことの起こり Webの画面では.新規入力をしようとすると.別ウィンドウ=子ウィンドウが開いて入力し.登録ボタンを押すと.子ウィンドウが閉じる仕組みがある. 子ウィンドウが閉じるだけなら問題ないが.一覧 ...

  8. Android--应用开发3(Android layout XML属性)

    Android layout XML属性 转载:http://www.cnblogs.com/playing/archive/2011/04/07/2008620.html Layout对于迅速的搭建 ...

  9. Bzoj-2820 YY的GCD Mobius反演,分块

    题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=2820 题意:多次询问,求1<=x<=N, 1<=y<=M且gcd( ...

  10. Spring配置MyBatis

    1.MyBatis配置文件(mybatis-config) <?xml version="1.0" encoding="UTF-8"?> <! ...