OGNL介绍

Posted aluoka

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了OGNL介绍相关的知识,希望对你有一定的参考价值。

OGNL介绍:
OGNL是Object-Graph Navigation Language的缩写,它是一种功能强大的表达式语言,通过它简单一致的表达式语法,可以存取对象的任意属性,调用对象的方法,遍历整个对象的结构图,实现字段类型转化等功能。它使用相同的表达式去存取对象的属性。这样可以更好的取得数据。
OGNL可以让我们用非常简单的表达式访问对象层,例如,当前环境的根对象为user1,则表达式person.address[0].province可以访问到user1的person属性的第一个address的province属性。
这种功能是模板语言的一个重要补充,像jsp2.0,velocity,jelly等等,都有类似的功能,但是ognl比它们完善得多,而且以一个独立的lib出现,方便我们构建自己的框架。
表达式:
OGNL支持各种纷繁复杂的表达式。但是最最基本的表达式的原型,是将对象的引用值用点串联起来,从左到右,每一次表达式计算返回的结果成为当前对象,后面部分接着在当前对象上进行计算,一直到全部表达式计算完成,返回最后得到的对象。OGNL则针对这条基本原则进行不断的扩充,从而使之支持对象树、数组、容器的访问,甚至是类似SQL中的投影选择等操作。
1. 基本对象树的访问
对象树的访问就是通过使用点号将对象的引用串联起来进行。
例如:xxxx,xxxx.xxxx,xxxx. xxxx. xxxx. xxxx. xxxx
2. 对容器变量的访问
对容器变量的访问,通过#符号加上表达式进行。
例如:#xxxx,#xxxx. xxxx,#xxxx.xxxxx. xxxx. xxxx. xxxx
3. 使用操作符号
OGNL表达式中能使用的操作符基本跟Java里的操作符一样,除了能使用 +, -, *, /, ++, --, ==, !=, = 等操作符之外,还能使用 mod, in, not in等。
4. 容器、数组、对象
OGNL支持对数组和ArrayList等容器的顺序访问:例如:group.users[0]
同时,OGNL支持对Map的按键值查找:
例如:#session[‘mySessionPropKey‘]
不仅如此,OGNL还支持容器的构造的表达式:
例如:"green", "red", "blue"构造一个List,#"key1" : "value1", "key2" : "value2", "key3" : "value3"构造一个Map
你也可以通过任意类对象的构造函数进行对象新建:
例如:new Java.net.URL("xxxxxx/")
5. 对静态方法或变量的访问
要引用类的静态方法和字段,他们的表达方式是一样的@[email protected]或者@[email protected](args):
6. 方法调用
直接通过类似Java的方法调用方式进行,你甚至可以传递参数:
例如:user.getName(),group.users.size(),group.containsUser(#requestUser)
7. 投影和选择
OGNL支持类似数据库中的投影(projection) 和选择(selection)。
投影就是选出集合中每个元素的相同属性组成新的集合,类似于关系数据库的字段操作。投影操作语法为 collection.XXX,其中XXX 是这个集合中每个元素的公共属性。
例如:group.userList.username将获得某个group中的所有user的name的列表。
选择就是过滤满足selection 条件的集合元素,类似于关系数据库的纪录操作。选择操作的语法为:collection.X YYY,其中X 是一个选择操作符,后面则是选择用的逻辑表达式。而选择操作符有三种:
? 选择满足条件的所有元素
^ 选择满足条件的第一个元素
$ 选择满足条件的最后一个元素
例如:group.userList.? #txxx.xxx != null将获得某个group中user的name不为空的user的列表。
 
技术图片

Ognl其实就是Map,它又分为一个根对象(Root)和多个非根对象
非根对象要通过"#key"访问,根对象可以省略"#key"
比如我们获取一个为根对象的的对象的属性,就只需要直接根据属性名就好了:String employeeName = (String) OnglExpression.getValue(“name”, ctx, e);
如果不是根对象: String managerName (String)OnglExpression.getValue("#manager.name",ctx, e);

 

对象取值和非根对象取值的现象,以及OGNL取值和赋值的案例

 1 package com.xy.test;
 2 
 3 import ognl.OgnlContext;
 4 import ognl.OgnlException;
 5 
 6 public class Demo1 
 7 
 8     /**
 9      * @param args
10      * @throws OgnlException
11      */
12     public static void main(String[] args)  
13         Employee e = new Employee();
14         e.setName("小李");
15 
16         Manager m = new Manager();
17         m.setName("张经理");
18 
19         // 创建OGNL下文,而OGNL上下文实际上就是一个Map对象
20         OgnlContext ctx = new OgnlContext();
21 
22         // 将员工和经理放到OGNL上下文当中去
23         ctx.put("employee", e);
24         ctx.put("manager", m);
25         ctx.setRoot(e);// 设置OGNL上下文的根对象
26 
27         /** ********************** 取值操作 *************************** */
28         // 表达式name将执行e.getName(),因为e对象是根对象(请注意根对象和非根对象表达式的区别)
29         String employeeName = (String) OnglExpression.getValue("name", ctx, e);
30         System.out.println(employeeName);
31 
32         // 表达式#manager.name将执行m.getName(),注意:如果访问的不是根对象那么必须在前面加上一个名称空间,例如:#manager.name
33         String managerName = (String) OnglExpression.getValue("#manager.name",
34                 ctx, e);
35         System.out.println(managerName);
36 
37         // 当然根对象也可以使用#employee.name表达式进行访问
38         employeeName = (String) OnglExpression.getValue("#employee.name", ctx,
39                 e);
40         System.out.println(employeeName);
41 
42         /** ********************** 赋值操作 *************************** */
43         OnglExpression.setValue("name", ctx, e, "小明");
44         employeeName = (String) OnglExpression.getValue("name", ctx, e);
45         System.out.println(employeeName);
46 
47         OnglExpression.setValue("#manager.name", ctx, e, "孙经理");
48         managerName = (String) OnglExpression.getValue("#manager.name", ctx, e);
49         System.out.println(managerName);
50 
51         OnglExpression.setValue("#employee.name", ctx, e, "小芳");
52         employeeName = (String) OnglExpression.getValue("name", ctx, e);
53         System.out.println(employeeName);
54     
55 
56 

OGNL向ValueStack压栈

后台定义属性和实现modelDriver接口,提供get和set方法

 1 private HttpServletRequest req;
 2     private Cal cal1=new Cal();
 3     private Cal cal2;
 4     private String sex;
 5     private String num1;
 6     
 7     
 8     public String getNum1() 
 9         return num1;
10     
11 
12 
13     public void setNum1(String num1) 
14         this.num1 = num1;
15     
16 
17 
18     public Cal getCal2() 
19         return cal2;
20     
21 
22 
23     public void setCal2(Cal cal2) 
24         this.cal2 = cal2;
25     
26 
27 
28     public String getSex() 
29         return sex;
30     
31 
32 
33     public void setSex(String sex) 
34         this.sex = sex;
35     
36     
37     /**
38      * implements ModelDriven
39      * @return
40      */
41     public String accept1() 
42         System.out.println("cal1:"+cal1);
43         System.out.println("num1:"+num1);
44         return "rs";
45     

运行显示cal1.num1有值,而num1却取不到值

这就和ValueStack的压栈有关系了,压栈的结构是先进后出,而ValueStack的取值是取到了值就会返回,不会往下取了。
而ValueStack对取值的压栈是先把xxxAction也就是我们通过set和get方法取值的方式先压入栈底,然后再把ModelDriver压入,所有会先取到通过ModelDriver来获取值的,而获取到了就返回了,导致后面的值不会获取了。

以上是关于OGNL介绍的主要内容,如果未能解决你的问题,请参考以下文章

OGNL

Struts2高级开发之OGNL

ognl表达式

Struts2------OGNL表达式

struts2 ValueStack

#%和$符号在OGNL表达式中的作用