Struts2之Ognl

上一篇算是看着学习了下ValueStack、ActionContext,如果还没明白他们之间是怎么回事,没关系,可以先学下Ognl,然后再回头看前面的可能就比较好理解了,我昨天也是一头雾水,现在把Ognl的学习了下,慢慢的有了感觉。

一、概念

OGNL表达式是(Object-Graph Navigation Language)是对象图形化导航语言。OGNL是一个开源的项目,struts2中默认使用OGNL表达式语言来显示数据。与serlvet中的el表达式的作用是一样的。OGNL表达式有下面以下特点:

1.支持对象方法调用,例如:objName.methodName();
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.操作集合对象

二、实践

这里定义了Address、User类

package com.cyw.test;

public class Address {

    public Address(String city, String street) {
        super();
        this.city = city;
        this.street = street;
    }

    private String city;
    public String getCity() {
        return city;
    }
    public void setCity(String city) {
        this.city = city;
    }
    public String getStreet() {
        return street;
    }
    public void setStreet(String street) {
        this.street = street;
    }
    private String street;
}
View Code
package com.cyw.test;

import java.util.Date;

public class User {
    private String name;
    private int age;
    private Date birthDay;
    private Address address;
    public User(String name, int age, Date birthDay, Address address) {
        super();
        this.name = name;
        this.age = age;
        this.birthDay = birthDay;
        this.address = address;
    }

    public Address getAddress() {
        return address;
    }
    public void setAddress(Address address) {
        this.address = address;
    }
    public Date getBirthDay() {
        return birthDay;
    }
    public void setBirthDay(Date birthDay) {
        this.birthDay = birthDay;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public int getAge() {
        return age;
    }
    public void setAge(int age) {
        this.age = age;
    }


}
View Code
        Address address=new Address("深圳市","坂田新天下");
        User user=new User("cyw",25,new Date(),address);
        //获取javabean的属性值
        String name=(String) Ognl.getValue("name", new HashMap(), user)    ;
        System.out.println(name);
        //获取对象的属性值
        String city=(String) Ognl.getValue("address.city", new HashMap(), user)    ;
        System.out.println(city);
        //修改属性值
        name=(String) Ognl.getValue("name='cuiyw'", new HashMap(), user)    ;
        System.out.println(name);
        Ognl.getValue("setName('cyw')", new HashMap(), user)    ;
        //调用对象方法
        name=(String) Ognl.getValue("getName()", new HashMap(), user)    ;
        System.out.println(name);
        
        //访问静态方法 格式:@包名+类名@静态方法
        UUID randomUUID=(UUID)Ognl.getValue("@java.util.UUID@randomUUID()", new HashMap(), user)    ;
        System.out.println(randomUUID.toString());
        //访问静态变量格式:@包名+类名@静态变量名
        double pi=(double)Ognl.getValue("@java.lang.Math@PI", new HashMap(), user);
        System.out.println(pi);
        
        //操作索引数组元素
        int []array={1,2,3,4};
        int first= (int) Ognl.getValue("[0]", new HashMap(), array);
        System.out.println(first);
        
        //操作集合
        List<User> userList=new ArrayList<User>();
        userList.add(user);
        name = (String) Ognl.getValue("[0].name", new HashMap(), userList);
        System.out.println(name);
        
        //操作Map
        Map<String,String> map=new HashMap<String,String>();
        map.put("key1", "cui");
        map.put("key2", "yan");
        name = (String) Ognl.getValue("key1", new HashMap(), map);
        System.out.println(name);
        //创建list
        List<String> list=(List<String>)Ognl.getValue("{'cui','yan'}",  new HashMap(), new Object());
        System.out.println(list.get(0));
        
        //创建map
        map=(Map)Ognl.getValue("#{'name':'cui','name2':'yan'}",  new HashMap(), new Object());
        System.out.println(map.get("name"));

三、ActionContext、ValueStack

  1.  ValueStack是一个接口,在struts2中使用OGNL表达式实际上是使用实现了ValueStack接口的类OgnlValueStack,这个类是OgnlValueStack的基础。
  2. ValueStack贯穿整个action的生命周期。每一个action实例都拥有一个ValueStack对象。其中保存了当前action对象和其他相关对象。
  3.  Struts2把ValueStack对象保存中名为struts.valueStack的request域中。

ActionContext:

OGNL中的上下文即struts2中的actionContext,OGNL中的root即struts2中的valueStack。

充当OGNL的context,是action的上下文,也可以叫做action的数据中心,本质是一个map,在其中,所有的数据都存放在这里,那其中到底存放了哪些东西呢,actionContext中存放数据的方式又是怎样的?

actionContext是一个map,所以其中都是以键值对的形式存储对象,如下图所示,

request、session、application这种我们熟知的作用域,注意是作用域,而不是对象,

paramters:这个是表单提交的参数,全部都会放到这个map中,

attr(attributes):三个作用域所有的属性都会放在该map下,如果有重复的,那么以request域中的为准。

VALUE_STACK:值栈,存放着valueStack对象,也就是说,通过ActionContext能够获取到valueStack。

如果我们使用actionContext.put();  那么会将该键值对直接放入到ActionContext下

ValueStack:值栈,本质是一个ArrayList,作用,充当ognl的root,给一次请求中共享数据的功能。

root:源码中的名称为CompoundRoot,它也是一个栈,而每次值栈中入栈和出栈等操作其实就是对CompoundRoot进行对应的操作。

Context:对actionContext的引用,也就是通过valueStack也能够获取到上下文,通过getContext();

在我们访问一个action时,会将action加入到栈顶,也就是action会在CompoundRoot的栈顶,而我们提交的各种表单参数(充当了ognl表达式)会在valueStack从顶向下查找对应的属性进行赋值。这就是值栈的作用。

参考:http://blog.csdn.net/v123411739/article/details/24052989

原文地址:https://www.cnblogs.com/5ishare/p/6636769.html