美文网首页
Struts2-OGNL

Struts2-OGNL

作者: xiang205012 | 来源:发表于2017-07-31 23:46 被阅读9次

    OGNL表达式语言介绍

    OGNL是Object Graphic Navigation Language(对象图导航语言)的缩写,它是一个开源项目。 Struts2框架使用OGNL作为默认的表达式语言。  
    
    OGNL相对其它表达式语言具有下面几大优势:  
        1. 支持对象方法调用,如xxx.doSomeSpecial();  
        2、支持类静态的方法调用和值访问,表达式的格式:
          @[类全名(包括包路径)]@[方法名 |  值名],例如:
          @java.lang.String@format('foo %s', 'bar')
          或@tutorial.MyConstant@APP_NAME;</pre>
        3、支持赋值操作和表达式串联,如price=100, discount=0.8,
        calculatePrice(),这个表达式会返回80;   
        4、访问OGNL上下文(OGNL context)和ActionContext;   
        5、操作集合对象。
    

    Ognl 有一个上下文(Context)概念,说白了上下文就是一个MAP结构,它实现了Java.utils.Map的接口.

    理解Struts2中的 ValueStack:

        ValueStack实际是一个接口,在Struts2中利用OGNL时,实际上使用的是实现了该接口的OgnlValueStack类,这个类是Struts2利用OGNL的基础。  
        ValueStack(值栈): 贯穿整个 Action 的生命周期(每个 Action 类的对象实例都拥有一个
                                  ValueStack 对象). 相当于一个数据的中转站. 在其中保存当前
                                  Action 对象和其他相关对象.
    

    Struts 框架把 ValueStack 对象保存在名为 “struts.valueStack” 的请求属性中,request中。

        在 ValueStack 对象的内部有两个逻辑部分:  
                ObjectStack: Struts  把Action和相关对象压入 ObjectStack 中--List  
                ContextMap: Struts 把各种各样的映射关系(一些 Map 类型的对象) 压入 ContextMap 中  
                    Struts 会把下面这些映射压入 ContextMap 中  
                            parameters: 该 Map 中包含当前请求的请求参数
                            request: 该 Map 中包含当前 request 对象中的所有属性
                            session: 该 Map 中包含当前 session 对象中的所有属性
                            application:该 Map 中包含当前 application  对象中的所有属性
                            attr: 该 Map 按如下顺序来检索某个属性: request, session, application
    

    理解OGNL Context:

                OgnlValueStack 类包含两个重要的属性   一个root(对象栈)和一个context(Map栈)。  
    
       *    其中root(对象栈,即CompundRoot类型)本质上是一个ArrayList.  
            里边保存各种和当前 Action 实例相关的对象.
            且默认将当前Action对象压入栈顶,如果action中没有手动将任何对象压入栈顶,
            那么栈顶对象一直是当前Action对象。
    
       *    而context 是一个Map(更确切的说是一个OgnlContext对象)
            也是对 ActionContext 的一个引用. 里边保存着各种 Map:
            requestMap, sessionMap, applicationMap, parametersMap, attr
      在这个OgnlContext对象(context)中,有一个默认的顶层对象 \_root,OGNL访问context中这个默认顶层对象中的元素时,是不需要#号的,直接通过元素的名称来进行访问,
    

    而访问其他对象时,如 request、session、attr等,则需要#号引用。

     注:Struts2将OgnlValueStack的root对象赋值给了OgnlContext 中的_root对象,  
        在OgnlValueStack的root对象中,保存着调用Action的实例,因此,在页面上通过Struts2标签访问Action 的属性时,就不需要通过#号来引用  
    
     总结:ognl Context包含 ObjectStack属性和ContextMap属性
    
      当Struts2接受一个请求时,会迅速创建ActionContext,ValueStack,action 。然后把action存放进ValueStack,所以action的实例变量可以被OGNL访问。 
    

    注意: Struts2中,OGNL表达式需要配合Struts标签才可以使用。如:<s:property value="name"/>

    读取值栈中的属性值

    • 访问对象属性不需要#号,访问Map中的属性需要加#号
    • 对于对象栈: 对象栈中某一个对象的属性值
      • 若想访问 Object Stack 里的某个对象的属性. 可以使用以下几种形式之一:
        • object.propertyName ; object['propertyName'] ; object["propertyName"]
      • ObjectStack 里的对象可以通过一个从零开始的下标来引用. ObjectStack 里的栈顶对象可以用 [0] 来引用,
        它下面的那个对象可以用 [1] 引用. [0].message:表示取第一个对象的message属性值
      • [n]的含义是从第n个对象开始搜索,但不限于第n个,如果第n个中没有,会到n+1个对象中找,依次类推下去,如果所有对象中都没找到,那就真的没有了。
      • 若从栈顶对象开始搜索, 则可以省略下标部分: message
      • 结合 s:property 标签: <s:property value="[0].message" /> 等价于 <s:property value="message" />
      • 默认情况下, Action 对象会被 Struts2 自动的放到值栈的栈顶.
    • Map 栈: request, session, application 的一个属性值 或 一个请求参数的值.
      • 使用<s:property value=""/>标签取值,如:
        ActionContext.getContext().put("myTest","HelloWorld");
        <s:property value="#request.myTest"/>
        取request中myTest这个key对应的value。
        ActionContext.getContext().put("test",test);
        <s:property value="#request.test.productName"/>
        EL方式取:${requestScope.test.productName}
        取request中test这个key对应test对象的productName属性值。
        注:其中#requet也可以不写,<s:property value="#test.productName"/>

    取值示例

    区分是对象站还是Map栈看使用的方法时push(Object)还是put(String,Object),前者是放到对象栈,后者放到Map栈。
    
        /**测试Map栈*/
        public String testBean() {
            ActionContext context = ActionContext.getContext();
            Ognl ognl = new Ognl();
            ognl.setName("zhangsan");
            ognl.setDescription("是个好人");
            context.put("singleBean", ognl);
            context.put("singleBean2", "testAction2");
    
    //       <s:Property value="#request.singleBean3">
    //       ServletActionContext.getRequest()
    //                      .setAttribute("singleBean3","testAction3");
    
            return "success";
        }
    
        /**测试对象栈*/
        public String testObjectStack() {
            // 把一个对象放入到栈顶
            Ognl ognl = new Ognl();
            ognl.setName("lisi");
            ActionContext.getContext().getValueStack().push(ognl);
            // 或者
            ActionContext.getContext().getValueStack().getRoot().add(0, ognl);
    
            // 获取栈顶元素
            ActionContext.getContext().getValueStack().peek();
            // 或者
            ActionContext.getContext().getValueStack().getRoot().get(0);
    
            // 弹栈
            ActionContext.getContext().getValueStack().pop();
    
            // 改变对象栈中的某个元素的值
            ActionContext.getContext().getValueStack().setValue("name", "aaa");
            ActionContext.getContext().put("bbb", "bbbb");
    
            String name = ActionContext.getContext().getValueStack()
                    .findValue("name").toString();
            String bbb = ActionContext.getContext().getValueStack().findValue("bbb")
                    .toString();
            System.out.println(name);
            System.out.println(bbb);
    
            return "success";
        }
    
    
        <!-- EL获取key为singleBean对象的name属性 -->
        actionContext.put : ${requestScope.singleBean.name} <br>
        <!-- EL获取key为singleBean2的value值 -->
        actionContext.put2 : ${requestScope.singleBean2} <br>
        <!-- OGNL获取key为singleBean对象的name属性 -->
        actionContext.put3 : <s:property value="#request.singleBean.name"/><br>
        <!-- OGNL获取key为singleBean2的value值 -->
        actionContext.put4 : <s:property value="singleBean2"/><br>
    
        /**测试迭代List*/
        public String testList() {
            List<Ognl> list = new ArrayList();
            Ognl ognl = new Ognl();
            ognl.setName("testList1");
            ognl.setDescription("testList111");
            list.add(ognl);
            Ognl ognl2 = new Ognl();
            ognl.setName("testList2");
            ognl.setDescription("testList222");
            list.add(ognl2);
            ActionContext.getContext().put("testList", list);
            return "success";
        }
    
        <!-- 迭代 List -->
        <s:iterator value="#testList">
            <!-- 直接用对象属性取值 -->
            <s:property value="name"/>
            <s:property value="description"/>
        </s:iterator>
    
        /**测试迭代Map*/
        public String testMap() {
            Map<String, Ognl> map = new HashMap();
            Ognl ognl = new Ognl();
            ognl.setName("开发部");
            ognl.setDescription("程序员比较多");
            map.put("a", ognl);
            Ognl ognl2 = new Ognl();
            ognl.setName("UI部");
            ognl.setDescription("女生比较多");
            map.put("b", ognl2);
            ActionContext.getContext().put("testMap", map);
    
            return "success";
        }
    
        <!-- 迭代 Map<String,Ognl> -->
        <s:iterator value="#testMap">
            <s:property value="key"/>
            <!-- 迭代Map其实就是迭代Map中的Entry。
                Map.Entry是Map声明的一个内部接口,此接口为泛型,定义为Entry<K,V>。
                            它表示Map中的一个实体(一个key-value对)。接口中有getKey(),getValue方法。
                           上面的value="key" -> entry.getKey()。 
                           下面的value=”value.name" -> entry.getValue().name            
            -->
            <s:property value="value.name"/>
        </s:iterator>
    
        /**测试listMap*/
        public String testListMap() {
            List<Map<String, Ognl>> listMap = new ArrayList();
            Map<String, Ognl> map = new HashMap();
            Ognl ognl = new Ognl();
            ognl.setName("开发部");
            ognl.setDescription("程序员比较多");
            map.put("a", ognl);
            Ognl ognl2 = new Ognl();
            ognl.setName("UI部");
            ognl.setDescription("女生比较多");
            map.put("b", ognl2);
    
            listMap.add(map);
    
            ActionContext.getContext().put("testListMap", listMap);
    
            return "success";
        }
    
        <!-- 迭代List<Map<String,Ognl>> -->
        <s:iterator value="#testListMap"><!-- 第一个是迭代List -->
            <s:iterator><!-- 第二个是迭代Map -->
                <s:property value="key"/>
                <s:property value="value"/>
            </s:iterator>
        </s:iterator>
    
        /**测试mapList*/
        public String testMapList() {
            Map<String, List<Ognl>> mapList = new HashMap();
            List<Ognl> list = new ArrayList();
            Ognl ognl = new Ognl();
            ognl.setName("testList1");
            ognl.setDescription("testList111");
            list.add(ognl);
            Ognl ognl2 = new Ognl();
            ognl.setName("testList2");
            ognl.setDescription("testList222");
            list.add(ognl2);
    
            mapList.put("ml", list);
    
            ActionContext.getContext().put("testMapList", mapList);
    
            return "success";
        }
        <!-- 迭代Map<String,List<Ognl>> -->
        <s:iterator value="#testMapList">
            <s:property value="key"/>
            <s:iterator value="value">
                <s:property value="name"/>
                <s:property value="description"/>
            </s:iterator>
        </s:iterator>
    
        /**测试listMapList*/
        public String testListMapList() {
            List<Map<String, List<Ognl>>> listMapList = new ArrayList();
            Map<String, List<Ognl>> mapList = new HashMap();
            List<Ognl> list = new ArrayList();
            Ognl ognl = new Ognl();
            ognl.setName("testList1");
            ognl.setDescription("testList111");
            list.add(ognl);
            Ognl ognl2 = new Ognl();
            ognl.setName("testList2");
            ognl.setDescription("testList222");
            list.add(ognl2);
    
            mapList.put("ml", list);
            listMapList.add(mapList);
    
            ActionContext.getContext().put("testListMapList", listMapList);
    
            return "success";
        }
    
       <!-- 迭代List<Map<String,List<Ognl>>> -->
       <s:iterator value="#testListMapList"><!-- 最外层list -->
            <s:iterator><!-- map -->
                <s:property value="key"/>
                <s:iterator value="value"><!-- map中的list -->
                    <s:property value="name"/>
                    <s:property value="description"/>
                </s:iterator>
            </s:iterator>
       </s:iterator>
    
    取值原则:当前栈顶对象是什么,
        如果是list,那么就是list中的第一个元素。
        如果是map,那么就是第一个entry。
           value="key" : 取出map 中 key 的值
           value="value" : 取出map中 key所对应的value值
    

    相关文章

      网友评论

          本文标题:Struts2-OGNL

          本文链接:https://www.haomeiwen.com/subject/tredlxtx.html