上一篇算是看着学习了下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; }
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; } }
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
- ValueStack是一个接口,在struts2中使用OGNL表达式实际上是使用实现了ValueStack接口的类OgnlValueStack,这个类是OgnlValueStack的基础。
- ValueStack贯穿整个action的生命周期。每一个action实例都拥有一个ValueStack对象。其中保存了当前action对象和其他相关对象。
- 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