OGNL表达式

OGNL表达式

1 什么是OGNL语言
你还记得 EL表达式语言么?没错OGNL也是表达式语言,不过它比EL可强大太多了。OGNL的全称为Object Graphic Navigation Language(对象图导航语言)。它是Struts2的默认表达式语言!
使用OGNL需要导入OGNL的Jar包:ognl-3.0.5.jar

OGNL的功能介绍:
	EL一样的JavaBean导航;
	调用对象方法;
	调用类的静态方法;
	索引数组元素;
	操作集合;

1.	EL可以读取JavaBean属性,OGNL使用起来与EL表达式有点相似
2.	EL操作的数据是域对象,OGNL操作的数据OgnlContext,可以在OgnlContext指定一个root对象,在不指定操作的对象时默认为root对象。

2 OGNL入门
为了可以执行OGNL表达式,所以我们必须要先学会怎么来使用Ognl类。为了更好的演示Ognl我们需要先创建一些JavaBean用来做测试。

public class Address {
	private String country;
	private String city;
	private String street;
……
}
public class Employee {
	private String name;
	private double salary;
	private Address address;
……
}

我们可以回忆一下EL的使用:${name},它会在所有域中去查找name这个域属性。也就是说,EL表达式也需要一个查询的范围。相同的道理,OGNL也需要一个查找的范围,它查询的范围是OgnlContext。OgnlContext其实就是一个Map,你可以向其内添加N个键值对。它还可以指定多个键值中的一个为根对象(root)! 

		OgnlContext cxt = new OgnlContext();
		Address add1 = new Address("中国", "北京", "大北窑");
		Employee e1 = new Employee("张三", 10000, add1);
		Address add2 = new Address("中国", "北京", "西三旗");
		Employee e2 = new Employee("李四", 12000, add2);		
		cxt.put("emp1", e1);
		cxt.put("emp2", e2);
		cxt.setRoot(e1);


演示OGNL表达式需要使用Ognl类,我们先从它的getValue()方法开始。这个方法需要三个参数,分别是:
	OGNL表达式;
	上下文对象;
	根对象。

		String name = (String)Ognl.getValue("#emp2.name", cxt, cxt.getRoot());
		System.out.println(name);


其中“#emp2.name”是OGNL表达式,查找上下文中的元素必须以“#”开关,其中emp2对应上下文中的键,“.name”表示调用该元素的getName()方法,即JavaBean导航。如果它这个OGNL表达式翻译成Java代码,即:((Employee)cxt.get(“emp2”)).getName()。

		String name = (String)Ognl.getValue("name", cxt, cxt.getRoot());
		System.out.println(name);

其中“name”为OGNL表达式,当没有使用“#”开始时,表达在使用根对象。所以“name”表达式可以理解为:cxt.getRoot().getName()。即输出“张三”。

		String name = (String)Ognl.getValue("address.street", cxt, cxt.getRoot());
		System.out.println(name);

  因为没有使用“#”开头,那么就是在使用根对象,即cxt.getRoot().getAddress().getStreet(),即输出“大北窑”。

1.	OgnlContext就是一个Map,指定操作的对象时需要使用“#”为前缀,后缀为Map的key为后缀;
2.	当没有使用“#”时,表示操作的对象为root对象。

3 OGNL常量
OGNL也可以使用常量:
	字符串常量:使用双引号,或单引号。如果字符串只有唯一字符时,必须使用双引号;
	字符常量:使用单引号;
	数值常量:与Java相同;
	boolean常量:与Java相同。
	OGNL也支持null常量。

1.	“hello”是字符串常量,’hello’也是字符串常量,’h’是字符常量;
2.	true、false为boolean类型常量;
3.	1.0、100为数值类型常量;
4.	null也是常量。

4 运算符
OGNL运算符基本与Java相同,但它还有一些特殊的运算符:
	逗号(,):用逗号分隔多个OGNL表达式,这些表达式会依次被执行,而最后一个表达式的值为整个表达式的值;
	大括号({}):用来创建列表,例如:{‘zhangSan’,’liSi’,’wangWu’}表示一个List;
	in和not in:in表示判断某个值是否在集合中,not in表达某个值是否不在集合中。

		double s = (Double)Ognl.getValue("name,#emp2.name,salary", cxt, cxt.getRoot());
		System.out.println(s);

  上面使用了逗号表达式,一共是3个OGNL表达式,它们会被依次运行,但整个整句表达式的值为最后一个OGNL表达式的值,即salary的值。

		boolean bool = (Boolean)Ognl.getValue("name in {'张三','李四'}", cxt, cxt.getRoot());
		System.out.println(bool);

  表达式“name in {‘张三’,’李四’}”首先需要得到name的结果,即根对象的name属性值,然后判断这个值是否在列表中存在,所以返回为true。

1.	逗号运算符很少使用,它的作用是把多个OGNL表达式连接成一个OGNL表达式,每个子表达式会从左到右依次运行,完整表达式的值来最右边表达式的值;
2.	in和not in,用于判断某个值在集合中是否存在;
3.	{}可以用来创建List集合。

4 设置JavaBean属性值(重点)
OGNL表达式不只是可以获取JavaBean属性值,不可以设置JavaBean属性值。但这需要使用Ognl类的setValue()方法。
		Ognl.setValue("#emp2.address.street", cxt, cxt.getRoot(), "育新");
		System.out.println(Ognl.getValue("#emp2.address.street",cxt, cxt.getRoot()));

表达式指定的是cxt中键为emp2的对象,然后导航到它的address属性,再导航到street属性,最终给该属性设置值为“育新”。

1.	“name”表示root对象的name属性;
2.	“address.city”表示root对象的address属性的city属性;
3.	“#emp.salary”表示上下文中key为emp的对象的salary属性。

5 调用对象方法
OGNL不只可以获取JavaBean属性,还可以调用对象方法。
		String s = (String)Ognl.getValue("'OGNL'.toLowerCase()", cxt, cxt.getRoot());
		System.out.println(s);

表达式“’OGNL’.toLowerCase()”表示调用字符串OGNL的toLowerCase()方法,千万要小心,在OGNL上添加单引或双引,指定其为字符串常量,不然会被误会来根对象的属性的。
当然,不只是可以调用字符串的方法,什么对象的方法都可以调用。

6 静态方法和静态属性
OGNL还可以调用类的静态方法,以及读取静态属性。操作静态方法或属性时,需要使用完整的类名称,并且需要使用两个“@”把类名称包含起来!
		String s = (String) Ognl.getValue(
				"@java.lang.String@format('%tF %<tT', new java.util.Date())",
				cxt, cxt.getRoot());
		System.out.println(s);

上面的表达式可以翻译成:java.lang.String.format(“%tF %<tT”, new java.util.Date())

OGNL对java.lang.Math对有特殊的待遇,如果是操作Math类的静态属性或静态方法,可以不用给出类名称,但“@”不可以省略。
		int max = (Integer)Ognl.getValue("@@max(1,2)", cxt, cxt.getRoot());
		System.out.println(max);
		double pi = (Double)Ognl.getValue("@@PI", cxt, cxt.getRoot());
		System.out.println(pi);

7 操作数组
  OGNL可以用来操作数组,使用下标法即可:
		String[] names = {"zhangSan", "liSi", "wangWu"};
		cxt.put("ns", names);
		String name = (String)Ognl.getValue("#ns[0]", cxt, cxt.getRoot());
		System.out.println(name);

8 操作集合
OGNL可以用来创建List和Map,先来创建一个List它。

		List<String> names = (List<String>)Ognl.getValue("{'zhangSan', 'liSi', 'wangWu'}", cxt, cxt.getRoot());
		System.out.println(names);

这段代码创建一个List,类型为ArrayList。
创建Map必须以“#”开头
		Map<String,String> map = (Map<String, String>)Ognl.getValue("#{'a':'A','b':'B'}", cxt, cxt.getRoot());
		System.out.println(map);

创建的Map默认类型为HashMap类型。还可以创建Map时指定Map的类型:
		Map<String, String> map = (Map<String, String>) Ognl.getValue(
				"#@java.util.LinkedHashMap@{'aa':'AA','bb':'BB'}", cxt,
				cxt.getRoot());
		System.out.println(map);

获取Map的值。
		String s = (String) Ognl.getValue(
				"#@java.util.LinkedHashMap@{'aa':'AA','bb':'BB'}['bb']", cxt,
				cxt.getRoot());
		System.out.println(s);

9 投影和选择
我们先来聊聊投影,如果有一个Employee的集合,可以通过投影获取所有的Employee的name属性值。这与数据库操作的查询指定列相似。
List<Employee> list = new ArrayList<Employee>();
list.add(new Employee("zhangSan", 10000));
list.add(new Employee("liSi", 11000));
list.add(new Employee("wangWu", 12000));
cxt.put("empList", list);
List<String> nameList = (List<String>) Ognl.getValue("#empList.{name}", cxt, cxt.getRoot());
System.out.println(nameList);

获取所有Employee的name属性。这相当于循环遍历list集合,然后调用每个Employee对象的getName()方法。

选择是给出一个条件,获取集合中满足条件的元素。这相当与select * from xxx where con。例如我们要获取salary > 10000的Employee对象。

		List<Employee> list = new ArrayList<Employee>();
		list.add(new Employee("zhangSan", 10000));
		list.add(new Employee("liSi", 11000));
		list.add(new Employee("wangWu", 12000));
		cxt.put("empList", list);
		List<Employee> empList = (List<Employee>) Ognl.getValue(
				"#empList.{?salary > 10000}", cxt, cxt.getRoot());
		System.out.println(empList);

  其中“{?salary > 10000}”中的“?”表示所有满足条件的元素都查询出来。还可以使用“^”或“$”,其中“^”表示查询第一个满足条件的元素,而“$”表示查询最后一个满足条件的元素。

 

你可能感兴趣的:(Ognl)