ognl表达式,访问对象数据和方法
1)什么是OGNL
Object Graphics Navigation Language,对象图导航语言.属于表达式语言,与EL相似.
a.El
el表达式主要用于替换jsp中的显示代码.利用El可以获取page,request,session,application
范围中获取数据显示.如:${name} 相当于在4个范围中访问xxx.getAttribute("name")的值
2).OGNL
A.ognl表达式功能比el强大,ognl引擎可以利用ognl表达式完成以下功能:
1)访问对象的属性,设置属性值或者获取属性值
2)调用对象的方法
3)调用静态的常量和方法
4)对集合进行过滤
5)运算符和操作符都可以使用
B.ognl基本语法
a.基本属性访问格式
例如:"id","name"
b.List集合和数组属性访问格式
例如:"friend[0]","number[0]"
c.复杂对象属性的访问
例如:"person.name","perList[0].name"
d.对象方法访问格式
例如:"name.toUpperCase()";
e.静态常量或方法访问格式
例如:"@java.lang.Math@PI"
3)OGNL工具体系结构
OGNL由3部分构成
a.OGNL引擎,负责解析执行ognl表达式
b.Root存储区,负责存储一个Object类型的对象,该存储区数据访问时,OGNL表达式格式为"属性"
ValueStack是ognl的根对象
c.Context存储区,负责存储一个Map类型的对象,该存储区数据访问时,OGNL表达式格式为"#key"
#访问的是非根对象属性
如图所示:
root 对象:Ognl操作的对象
context 对象:就是一个Map,用于存放一个和整个系统都相关的公共数据
当有了Ognl引擎,我们就可以访问各种各样的root对象(比如Foo 对象、Emp 对象、Dept对
象等),在访问中有一些数据是每一次访问都需要用到的,这些数据就可以保存在context对象中
============================================
OGNL基础语法演示
============================================
a.创建Foo对象
import java.util.List;
import java.util.Map;
public class Foo {
private Integer id;
private String name;
private String[] arry;
private List<String> list;
private Map<String, String> map;
public Integer getId() {return id;}
public void setId(Integer id) {this.id = id;}
public String getName() {return name;}
public void setName(String name) {this.name = name;}
public String[] getArry() {return arry;}
public void setArry(String[] arry) {this.arry = arry;}
public List<String> getList() {return list;}
public void setList(List<String> list) {this.list = list;}
public Map<String, String> getMap() {return map;}
public void setMap(Map<String, String> map) {this.map = map;}
===========================================================================
b.演示ongl表达式的使用方式:
import java.util.Arrays;
import java.util.HashMap;
import ognl.Ognl;
import org.junit.Test;
public class TestOgnl {
@Test
/**
* OGNL的基础语法
*/
public void tst1() throws Exception {
Foo foo = new Foo();
foo.setId(100);
foo.setName("Java");
foo.setArry(new String[] { "one", "two", "three" });
foo.setList(Arrays.asList("A", "B", "C"));
HashMap<String, String> map =
new HashMap<String, String>();
map.put("one", "Java");
map.put("two", "JavaJava");
map.put("three", "JavaJavaJava");
foo.setMap(map);
/* Ognl引擎访问对象的格式:
* Ognl.getValue("OGNL表达式", root对象); //roo
*/
//1. 基本类型属性(包括String)
System.out.println("##1基本类型属性##");
System.out.println(Ognl.getValue("id", foo));
System.out.println(Ognl.getValue("name", foo));
//2. 数组、List属性:属性名[下标]
System.out.println("##2数组、List属性##");
System.out.println(Ognl.getValue("arry[0]", foo));
System.out.println(Ognl.getValue("list[1]", foo));
//3. Map属性
System.out.println("##3Map属性##");
System.out.println(Ognl.getValue("map.one", foo));
System.out.println(Ognl.getValue("map['two']", foo));
//map['two']中的two是key
//4. 基本运算
System.out.println("##4基本运算##");
System.out.println(Ognl.getValue("id+100", foo));
System.out.println(Ognl.getValue("\"What is \"+name", foo));
System.out.println(Ognl.getValue("\"name: \" + name + \" id: \" +id",
foo));
System.out.println(Ognl.getValue("id > 150", foo));
//5. 调用方法
System.out.println("##5调用方法##");
System.out.println(Ognl.getValue("name.toUpperCase()", foo));
System.out.println(Ognl.getValue("list.size()", foo));
//注意:方法的参数也可以使属性
System.out.println(
Ognl.getValue("map['three'].lastIndexOf(name)", foo));
//6. 调用静态方法,以取出的属性为参数
//调用静态方法的格式:@类名@方法名
System.out.println("##6调用静态方法##");
System.out.println(
Ognl.getValue("@java.uti l.Arrays@toString(arry)",foo));
//Ognl中只能创建List和Map对象
//7. 创建的List对象
//这种方法更方便地临时创建一个List对象
System.out.println("##7创建的List对象##");
Object obj = Ognl.getValue("{1,2,3,4,5}", null);
System.out.println(obj.getClass().getName());
System.out.println(obj);
//8. 创建的Map对象
//注意:“#”号丌能丢
System.out.println("##8创建的Map对象##");
obj = Ognl.getValue(
"#{1:'java',2:'javajava',3:'javajavajava'}", null);
System.out.println(obj.getClass().getName());
System.out.println(obj);
}
}
A. OGNL在Struts2中的应用
1)在xwork中对ognl工具结构进行一些改造(把root存储区变为栈的结构.如果寻找"name"的值,会从
栈顶中开始寻找,如果找到了,就返回值,没有找到,依次往栈底位置方向寻找)
2)ValueStack对象
ValueStack对象负责存储与Struts请求处理相关的数据,例如请求的数据,request,session,
application,action对象的引用.
ValueStack结构参考valuestack.jpg
当客户发送一个action请求到打控制器,控制器会根据请求创建一个valuestack对象,利用该对象存储
request,action,session等信息
默认情况下,存储结构如下:
a.root区域(栈结构),存储当前请求对应的Action对象,处于栈顶位置.
b.context区域(Map),存储当前请求request,session,application对象的引用
B. XWork 中对 OGNL 的扩展
在之前讲的Ognl的应用是通用的,接下来讲解XWork 中对 Ognl做的改劢。
图示演示
OGNL引擎
CompoundRoot对象: 在XWork 中,root对象被改为类似“栈”一样的存储空间,
在该对象空间内可以存放多个root对象;
当取数据时符合“栈”的规则,如果OGNL表达式是“name“,
在CompoundRoot从栈顶开始依次看是否有name 属性...
Context(Map)对象
Struts2 在启劢时,会创建一个ValueStrack 对象
当用户发送请求到对应的Action时,Struts2 会把当前被请求的Action01 放入 CompoundRoot
对象的“栈空间”栈顶,请求结束,Action01 会被清除。
(当下一次另一个请求到来时,Struts2 会把该请求对应的Action02放入“栈顶”)
所以,我们可以通过Ognl表达式访问CompoundRoot对象栈顶的Action。