OGNL表达式和ValueStack值栈

1.OGNL和ValueStack值栈简介  

        OGNL是Object-Graph Navigation Language(对象图导航语言)的缩写,它是一种功能强大的表达式语言,通过它简单一致的表达式语法,可以存取对象的任意属性,调用对象的方法,遍历整个对象的结构图,实现字段类型转化等功能。它使用相同的表达式去存取对象的属性。Struts2框架内置了OGNL,OGNL本身也是一个项目,它是可以单独使用。

        ValueStack基于ognl,作用是在struts2框架中来存储数据的容器.

        valueStack存放数据,ognl从中取得数据.

2.ValueStack的内部结构:

     ValueStack主要由两部分组成:

        CompoundRoot  root:    实质是一个ArrayList;

        Map<String,Object> context:    实质是一个Map;  //ognl获取context中数据要加#号

3.ValueStack的获取:

                        ValueStack valuestack = ActionContext.getContext().getValueStack();

       这里的ActionContext是action的上下文,作用是管理context,当前Action类的ActionContext通过它的静态方法getContext() 获取

                        ActionContext actioncontext = ActionContext.getContext();

          每有一次http请求,struts2就会创建对应的ActionContext,它和当前线程绑定.

         浏览器发送request---创建ValueStack对象---创建ActionContext对象(管理context)---创建Action对象

4.数据的存取

    (1)ValueStack存储数据.(主要是向root中存储)
        手动存储:

               push方法:直接将对象压入到ValueStack的root

               set方法: 创建一个Map压入到root,再把数据以键值对<k,v>的形式存放到这个map中.

                        public  String  execute(){

                                ValueStack  valuestack = ActionContext.getContext().getValueStack();

                                valuestack.push("aaa");//push方法

                                valuestack.set("username","aaa");//set方法

                                return  "success";

                        }

        自动存储:       

   在框架源码的DefaultActionInvocation类的init方法内:首先创建了当前访问的Action对象,然后通过stack.push(action)将当前访问的Action对象存放到valueStack的root中,也就是每次请求访问action的时候,都会构造出action对象并将这个action对象存储到valueStack的root(ArrayList)中。

   在浏览器访问action的时候ModelDrivernInterceptor这个拦截器会执行如下代码:

              

        也就是在访问action类时,会先判断action是否实现了ModelDriven接口,如果实现了这个接口,就通过action类里实现的getModel()方法获取model对象push到root中.

    (2)ognl在jsp页面中的获取ValueStack中的数据:
       (a).在jsp页面上加上taglib指令:

           <%  taglib uri="/struts-tags" prefix="s" %>

            

      (b)使用ognl表达式获取数据:

           <s : property value="username"/>可以查看root中存放的username

            

          <s : property value="[0]"/> 可以查看root中从第0项(栈最顶端)开始向下的所有内容.

         <s : property value="[0].top"/> 可以查看root中第0项的内容.

         <s : property value="#parameters"/> 从context 中获取封装请求参数的map对象

        获取自动存放的数据需要在action类中提供get方法.

 (3)一些常见的获取数据标签:
        (a) 获取错误信息:

             让action类继承ActionSupport类,ActionSupport类中定义了addActionError方法,在页面中可以直接使用struts2提供的标签 <s : actionerror /> 来显示错误信息:

                

              ActionSupport类中还有addActionMessage方法和addFieldError方法可以传递简单的字符串.

                              this.addActionMessage("用户名不能为空");

                              this.addFieldError("password","密码错误");

              在页面上可以相应的使用<s: actionmessage/>  <s: fielderror  fieldName="password" />来获取

      (b)使用<s: iterator>标签来完成遍历展示集合中的对象.

            ①<s: iterator value="存入root的集合名" var="xxx">

                      //带var属性,每次取得一个对象以 xxx 为key存放到context中.

                      //再从context中获取该对象,然后获取对象的属性.

                      <tr>

                        <td><s: property value="#xxx.属性名"></td>//注意加#号,因为此时是从context中取值

                        <td><s: property value="#xxx.属性名"></td>

                     </tr>

                </s: iterator>

            ②<s: iterator value="存入root的集合名" > 

                  //不带var属性,每次取得一个对象存放到root中

                  //再从root中获取该对象,然后获取对象的属性.

                      <tr>

                            <td><s: property value="[0].top.属性名"></td>//获取刚存入root顶部的元素

                            <td><s: property value="属性名"></td>

                     </tr>

                </s: iterator>

             ③也可以将集合声明成action类的属性,并提供get方法,这样也能在页面获取到数据.

                        具体步骤等有时间再研究.       _(:з」∠)_