zoukankan      html  css  js  c++  java
  • 应用:ValueStack

    理解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属性:张三

  • 相关阅读:
    Linnia学习记录
    漫漫考研路
    ENS的学习记录
    KnockoutJS 3.X API 第四章 数据绑定(4) 控制流with绑定
    KnockoutJS 3.X API 第四章 数据绑定(3) 控制流if绑定和ifnot绑定
    KnockoutJS 3.X API 第四章 数据绑定(2) 控制流foreach绑定
    KnockoutJS 3.X API 第四章 数据绑定(1) 文本及样式绑定
    KnockoutJS 3.X API 第三章 计算监控属性(5) 参考手册
    KnockoutJS 3.X API 第三章 计算监控属性(4)Pure computed observables
    KnockoutJS 3.X API 第三章 计算监控属性(3) KO如何实现依赖追踪
  • 原文地址:https://www.cnblogs.com/yaowen/p/4826406.html
Copyright © 2011-2022 走看看