Struts2-OGNL

OGNL表达式语言介绍

OGNL是Object Graphic Navigation Language(对象图导航语言)的缩写,它是一个开源项目。 Struts2框架使用OGNL作为默认的表达式语言。  

OGNL相对其它表达式语言具有下面几大优势:  
    1. 支持对象方法调用,如xxx.doSomeSpecial();  
    2、支持类静态的方法调用和值访问,表达式的格式:
      @[类全名(包括包路径)]@[方法名 |  值名],例如:
      @java.lang.String@format('foo %s', 'bar')
      或@tutorial.MyConstant@APP_NAME;
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标签才可以使用。如:

读取值栈中的属性值

  • 访问对象属性不需要#号,访问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 标签: 等价于
    • 默认情况下, Action 对象会被 Struts2 自动的放到值栈的栈顶.
  • Map 栈: request, session, application 的一个属性值 或 一个请求参数的值.
    • 使用标签取值,如:
      ActionContext.getContext().put("myTest","HelloWorld");

      取request中myTest这个key对应的value。
      ActionContext.getContext().put("test",test);

      EL方式取:${requestScope.test.productName}
      取request中test这个key对应test对象的productName属性值。
      注:其中#requet也可以不写,

取值示例

区分是对象站还是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");

//       
//       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";
    }


    
    actionContext.put : ${requestScope.singleBean.name} 
actionContext.put2 : ${requestScope.singleBean2}
actionContext.put3 :
actionContext.put4 :
    /**测试迭代List*/
    public String testList() {
        List 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";
    }

    
    
        
        
        
    
    /**测试迭代Map*/
    public String testMap() {
        Map 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";
    }

    
    
        
        
        
    
    /**测试listMap*/
    public String testListMap() {
        List> listMap = new ArrayList();
        Map 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";
    }

    
    
        
            
            
        
    
    /**测试mapList*/
    public String testMapList() {
        Map> mapList = new HashMap();
        List 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";
    }
    
    
        
        
            
            
        
    
    /**测试listMapList*/
    public String testListMapList() {
        List>> listMapList = new ArrayList();
        Map> mapList = new HashMap();
        List 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,那么就是list中的第一个元素。
    如果是map,那么就是第一个entry。
       value="key" : 取出map 中 key 的值
       value="value" : 取出map中 key所对应的value值

你可能感兴趣的:(Struts2-OGNL)