理解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. Ajax时代 SQL注入依然是隐患

    许多网站程序在编写时,没有对用户输入数据的合法性进行判断,使应用程序存在安全隐患.用户可以提交一段数据库查询代码(一般是在浏览器地址栏进行,通过正常的www端口访问),根据程序返回的结果,获得某些想得 ...

  2. 【众秒之门 JavaScript与jQuery技术精粹 #BOOK#】第1章 初学JavaScript需知的七件事

    <!DOCTYPE html> <html lang="zh-CN"> <head> <meta charset="utf-8& ...

  3. 如何在同一台服务器上安装多套通达OA

    本人最近研究了在同一服务器安装多套通达OA的方法:发现网上关于这个话题的文章比较少,于是录制成视频,在此发布,希望对有这方面需求的朋友有所帮助: http://blog.163.com/zhuwei_ ...

  4. android LayoutInflater和inflate()方法的用法(转载)

    原文出处:http://www.cnblogs.com/top5/archive/2012/05/04/2482328.html 在实际开发中LayoutInflater这个类还是非常有用的,它的作用 ...

  5. 通达信自动交易软件 z

    1.要善用spy++ 2.不同的控件主要靠GetDlgCtrlID去区分 3.要获得另一个进程的焦点窗口(GetFocus)需要调用AttachThreadInput 4.尽量少用keybd_even ...

  6. MSP430F149流水灯闪烁以及数码管的显示

    今天下午写了一个流水灯闪烁的实验,总的来说,不难,因为这块板子集合的电路图没有上一块那么复杂,所以总的来说,还是比较顺手,开始的时候,出现流水灯没有流转的现象,原来是没有加入延时函数,后来经过调整,结 ...

  7. Notepad++中调用cl.exe编译器(Windows)

    Notepad++中调用cl.exe编译器(Windows) 近来在notepad++中写代码,写完后总是习惯性的想去VS里面编译一下,看看代码是否有误.但有时候一些零碎的小文件总是懒得再VS中打开, ...

  8. ruby 资料整理

    http://blog.csdn.net/maingalaxy/article/details/46013393 http://blog.csdn.net/dzl84394/article/detai ...

  9. 【暑假】[深入动态规划]UVa 10618 Fun Game

    UVa 10618 Fun Game 题目: http://acm.hust.edu.cn/vjudge/problem/viewProblem.action?id=36035 思路:   一圈人围坐 ...

  10. position属性

    所有主流浏览器支持position属性: 任何版本的ie浏览器都不支持属性值“inherit”. position属性规定元素的定位类型,任何元素都可以定位,不过绝对定位或固定元素会生成一个块级框,不 ...