在学习Struts2中的OGNL和值栈的时候,遇到了OGNL,看了一些后还是发下对这个OGNL 完全模糊,在此节单独对OGNL进行学习。
目的是学完后知道OGNL是来干嘛的?可以怎么使用。
OGNL是Object-Graph Navigation Language的缩写,它是一种功能强大的表达式语言,通过它简单一致的表达式语法,可以存取对象的任意属性,调用对象的方法,遍历整个对象的结构图,实现字段类型转化等功能。它使用相同的表达式去存取对象的属性。 ——百度百科
OGNL我们看到最多的就是和Struts2的标签结合使用,但其实OGNL离开了Struts2也是可以的,只是用在Struts2中,就必须和标签库结合才能使用。
这篇文章就先讲讲OGNL不结合Struts2的一些用法,下篇文章再讲OGNL在Struts2中的用法。
在类中使用OGNL表达式,和两个类息息相关,分别是OgnlContext类和Ognl类。
Ognl类:This class provides static methods for parsing and interpreting OGNL expressions.根据官方解释,这个类是提供一些静态方法去解析表达式。
OgnlContext:This class defines the execution context for an OGNL expression.该类定义OGNL表达式的执行上下文。
public class OgnlContext extends Object implements Map {}
OgnlContext类实现了Map接口,所以它也是一个Map,可以通过put方法往该上下文环境中放元素。该上下文环境中,有两种对象:根对象和普通对象。我们可以使用它的setRoot方法设置根对象。根对象只能有一个,而普通对象则可以有多个。因为它实现了java.utils.Map 的接口。OgnlContext(ognl上下文)=根对象(1个)+非根对象(n个),非根对象要通过"#key"访问,根对象可以省略"#key"。
2.Ognl获取普通对象和根对象的方法
在上下文环境中,有根对象和普通的对象,两者的获取方式有所不同:获取根对象的属性值,可以直接使用属性名作为表达式,也可以使用#对象名.属性名的方式;获取普通对象的属性值,则必须使用#对象名.属性名的方式获取。(可以将普通对象设置为根对象,但只能有一个根对象,后面设置的根对象会覆盖前面的根对象)下面举例说明。
1 package OGNL; 2 3 import java.util.List; 4 5 public class School { 6 7 private String name; 8 private List<Teacher> teachers; 9 10 11 public School() { 12 super(); 13 } 14 15 16 public School(String name, List<Teacher> teachers) { 17 super(); 18 this.name = name; 19 this.teachers = teachers; 20 } 21 22 23 /** 24 * @return the name 25 */ 26 public String getName() { 27 return name; 28 } 29 /** 30 * @param name the name to set 31 */ 32 public void setName(String name) { 33 this.name = name; 34 } 35 /** 36 * @return the teachers 37 */ 38 public List<Teacher> getTeachers() { 39 return teachers; 40 } 41 /** 42 * @param teachers the teachers to set 43 */ 44 public void setTeachers(List<Teacher> teachers) { 45 this.teachers = teachers; 46 } 47 48 49 } 50 51 package OGNL; 52 53 public class Teacher { 54 55 private String name; 56 private String gender; 57 private int age; 58 59 60 public Teacher() { 61 super(); 62 } 63 64 public Teacher(String name, String gender, int age) { 65 super(); 66 this.name = name; 67 this.gender = gender; 68 this.age = age; 69 } 70 /** 71 * @return the name 72 */ 73 public String getName() { 74 return name; 75 } 76 /** 77 * @param name the name to set 78 */ 79 public void setName(String name) { 80 this.name = name; 81 } 82 /** 83 * @return the gender 84 */ 85 public String getGender() { 86 return gender; 87 } 88 /** 89 * @param gender the gender to set 90 */ 91 public void setGender(String gender) { 92 this.gender = gender; 93 } 94 /** 95 * @return the age 96 */ 97 public int getAge() { 98 return age; 99 } 100 /** 101 * @param age the age to set 102 */ 103 public void setAge(int age) { 104 this.age = age; 105 } 106 107 } 108 109 package OGNL; 110 111 import java.util.ArrayList; 112 import java.util.List; 113 114 import ognl.Ognl; 115 import ognl.OgnlContext; 116 import ognl.OgnlException; 117 118 public class Test { 119 120 public static void main(String args[]) throws OgnlException{ 121 122 //定义一个老师对象 123 Teacher t1 = new Teacher("zhangsan","男",30); 124 List<Teacher> teachers =new ArrayList<Teacher>(); 125 teachers.add(t1); 126 127 //定义一个学校对象 128 School sc = new School("China", teachers); 129 130 //创建一个OgnlContext对象 131 OgnlContext context = new OgnlContext(); 132 133 //将老师和学校放入上下文环境中 134 context.put("t1", t1); 135 context.put("sc", sc); 136 137 //未设置根对象之前,根对象为null 138 System.out.println("0000:"+context.getRoot()); 139 140 //设置学校为根对象 141 context.setRoot(sc); 142 System.out.println("1111:"+context.getRoot()); 143 //若继续设置根对象,会覆盖前面的根对象 144 //context.setRoot(t1); 145 146 //获取根对象属性 147 //获取根对象的属性值,可以直接使用属性名作为表达式,也可以使用#对象名.属性名的方式; 148 Object expression = Ognl.parseExpression("name"); 149 //Object expression = Ognl.parseExpression("#sc.name"); 150 151 Object result = Ognl.getValue(expression, context, context.getRoot()); 152 // 获取根对象的信息,使用#获取上下文中的属性值时,必须使用带Map context参数getValue方法,指定上下文环境 153 // 获取根对象的信息,直接获取,没有使用#,则可以使用不带Map context参数getValue方法 154 Object result1 = Ognl.getValue(expression, context.getRoot()); 155 System.out.println("2222:"+result); 156 System.out.println("2222:"+result1); 157 158 //获取普通对象的属性值,则必须使用#对象名.属性名的方式获取 159 expression = Ognl.parseExpression("#t1.name"); 160 result = Ognl.getValue(expression, context, context.getRoot()); 161 System.out.println("3333:"+result); 162 } 163 164 }
运行测试代码:这种方法通过属性来获取属性值
0000:null
1111:OGNL.School@11028347
2222:China
2222:China
3333:zhangsan
总结:
1.根对象只能有一个,当你尝试设置多个的时候,后面的会覆盖前面的。
2.访问根对象中的属性,可以直接使用属性名,或者#对象名.属性名,但不能使用对象名.属性名,不然它会认为这是根对象中的一个属性叫对象名,然后访问这个属性的名叫属性名的属性值。
3.不使用#获取根对象中的属性值时, 使用getValue方法可以不指定上下文环境,因为第三个参数已经得到了根对象,它指定去根对象中找。如果获取普通对象的属性,则必须在getValue方法中指定上下文环境,因为你不知道它找不到。
4.通过根对象间接获取普通对象的属性时,比如List集合,使用下标去获取
Ognl不但可以访问我们自己定义的类的属性和方法,还可以访问Java API中的静态方法和静态字段。
1 package OGNL; 2 3 import java.util.ArrayList; 4 import java.util.List; 5 6 import ognl.Ognl; 7 import ognl.OgnlContext; 8 import ognl.OgnlException; 9 10 public class Test { 11 12 public static void main(String args[]) throws OgnlException{ 13 14 //定义一个老师对象 15 Teacher t1 = new Teacher("zhangsan","男",30); 16 List<Teacher> teachers =new ArrayList<Teacher>(); 17 teachers.add(t1); 18 19 //定义一个学校对象 20 School sc = new School("China", teachers); 21 22 //创建一个OgnlContext对象 23 OgnlContext context = new OgnlContext(); 24 25 //将老师和学校放入上下文环境中 26 context.put("t1", t1); 27 context.put("sc", sc); 28 29 //未设置根对象之前,根对象为null 30 System.out.println("根对象:"+context.getRoot()); 31 32 //设置学校为根对象 33 context.setRoot(sc); 34 System.out.println("设置根对象:"+context.getRoot()); 35 //若继续设置根对象,会覆盖前面的根对象 36 //context.setRoot(t1); 37 38 //获取根对象属性 39 //获取根对象的属性值,可以直接使用属性名作为表达式,也可以使用#对象名.属性名的方式; 40 Object expression = Ognl.parseExpression("name"); 41 //Object expression = Ognl.parseExpression("#sc.name"); 42 43 Object result = Ognl.getValue(expression, context, context.getRoot()); 44 // 获取根对象的信息,使用#获取上下文中的属性值时,必须使用带Map context参数getValue方法,指定上下文环境 45 // 获取根对象的信息,直接获取,没有使用#,则可以使用不带Map context参数getValue方法 46 Object result1 = Ognl.getValue(expression, context.getRoot()); 47 System.out.println("获取根对象的属性值:"+result); 48 System.out.println("获取根对象的属性值:"+result1); 49 50 //获取普通对象的属性值,则必须使用#对象名.属性名的方式获取 51 expression = Ognl.parseExpression("#t1.name"); 52 result = Ognl.getValue(expression, context, context.getRoot()); 53 System.out.println("获取普通对象的属性值:"+result); 54 55 //调用根对象中的方法 56 expression = Ognl.parseExpression("getName()"); 57 expression = Ognl.parseExpression("#sc.getName()"); 58 result = Ognl.getValue(expression, context, context.getRoot()); 59 System.out.println("调用根对象中的方法:"+result); 60 61 //调用普通对象中的方法 62 expression = Ognl.parseExpression("#t1.getAge()"); 63 result = Ognl.getValue(expression, context, context.getRoot()); 64 System.out.println("调用普通对象中的方法:"+result); 65 expression = Ognl.parseExpression("#t1.getName().length()"); 66 result = Ognl.getValue(expression, context, context.getRoot()); 67 System.out.println("调用普通对象中的方法:"+result); 68 69 //调用根对象中的静态方法 70 expression = Ognl.parseExpression("test00()"); 71 expression = Ognl.parseExpression("#sc.test00()"); 72 result = Ognl.getValue(expression, context, context.getRoot()); 73 System.out.println("调用根对象中的静态方法:"+result); 74 75 //调用API中的静态方法 76 expression = Ognl.parseExpression("@java.lang.Math@floor(4.5)"); 77 result = Ognl.getValue(expression, context, context.getRoot()); 78 System.out.println("调用API中的静态方法:"+result); 79 80 //调用API中的静态属性 81 expression = Ognl.parseExpression("@java.lang.Math@PI"); 82 result = Ognl.getValue(expression, context, context.getRoot()); 83 System.out.println("调用API中的静态属性:"+result); 84 85 } 86 87 }
在school.java中新加了一个静态函数:
1 public static String test00(){ 2 3 return "thank you"; 4 }
运行上面的测试code:
根对象:null
设置根对象:OGNL.School@11028347
获取根对象的属性值:China
获取根对象的属性值:China
获取普通对象的属性值:zhangsan
调用根对象中的方法:China
调用普通对象中的方法:30
调用普通对象中的方法:8
调用根对象中的静态方法:thank you
调用API中的静态方法:4.0
调用API中的静态属性:3.141592653589793.
所以到此我们可以看到OGNL实际上就是提供另一种方式来调用对象的任意属性和方法。
Ognl表达式可以创建实例对象,以及获取实例对象中的属性,下面我们看看怎么通过Ognl创建一个集合、map以及通过Ognl获取里面的元素。
1 package OGNL; 2 3 import java.util.ArrayList; 4 import java.util.Collections; 5 import java.util.HashMap; 6 import java.util.List; 7 import java.util.Map; 8 9 import ognl.Ognl; 10 import ognl.OgnlContext; 11 import ognl.OgnlException; 12 13 public class Test02 { 14 15 public static void main(String[] args) throws OgnlException { 16 17 OgnlContext context = new OgnlContext(); 18 19 // 通过Ognl可以创建java的实例对象,只有是类的完整路径 20 Object expression = Ognl.parseExpression("new java.util.ArrayList()"); 21 Object result = Ognl.getValue(expression, context, context.getRoot()); 22 System.out.println("Ognl创建实例:"+result); 23 24 //注意这种自定义的类,一定要填写类的完整路径 25 expression = Ognl.parseExpression("new OGNL.Teacher(‘zhangsan‘,‘男‘,30)"); 26 result = Ognl.getValue(expression, context, context.getRoot()); 27 System.out.println("Ognl创建实例:"+result); 28 29 // 通过Ognl可以创建一个初始化的List 30 expression = Ognl.parseExpression("{‘a‘, ‘b‘, ‘c‘, ‘d‘}"); 31 //expression = Ognl.parseExpression("[‘a‘, ‘b‘, ‘c‘, ‘d‘]"); //这个报错 32 result = Ognl.getValue(expression, context, context.getRoot()); 33 System.out.println("Ognl初始化List:"+result); 34 35 // 通过Ognl可以创建一个初始化的Map,注意此时得加上#符号 36 expression = Ognl.parseExpression("#{‘a‘:‘aa‘, ‘b‘:‘bb‘, ‘c‘:‘cc‘, ‘d‘:‘dd‘}"); 37 // 创建指定类型的Map 38 // expression = Ognl.parseExpression("#@java.util.TreeMap@{‘a‘:‘aa‘, ‘b‘:‘bb‘, ‘c‘:‘cc‘, ‘d‘:‘dd‘}"); 39 result = Ognl.getValue(expression, context, context.getRoot()); 40 System.out.println("Ognl初始化Map:"+result); 41 42 // 通过Ognl访问数组中的元素 43 String[] name1 = {"liu", "xu"}; 44 context.put("name1", name1); 45 // 直接通过数组名+下标 46 expression = Ognl.parseExpression("#name1[1]"); 47 result = Ognl.getValue(expression, context, context.getRoot()); 48 System.out.println("通过Ognl访问数组中的元素:"+result); 49 50 // 通过Ognl访问集合中的元素 51 List<String> name2 = new ArrayList<String>(); 52 Collections.addAll(name2, name1); //将name1中的数据copy到name2中。 53 context.put("name2", name2); 54 // 直接通过集合名+下标 55 expression = Ognl.parseExpression("#name2[0]"); 56 result = Ognl.getValue(expression, context, context.getRoot()); 57 System.out.println("通过Ognl访问集合中的元素:"+result); 58 59 // 通过Ognl访问Map中的元素 60 Map<Integer, String> name3 = new HashMap<Integer, String>(); 61 name3.put(1, "liu"); 62 name3.put(2, "xu"); 63 context.put("name3", name3); 64 // 直接通过map名+key 65 expression = Ognl.parseExpression("#name3[1]"); 66 result = Ognl.getValue(expression, context, context.getRoot()); 67 System.out.println("通过Ognl访问Map中的元素 :"+result); 68 69 } 70 71 }
运行结果:
Ognl创建实例:[]
Ognl创建实例:OGNL.Teacher@2aaf7cc2
Ognl初始化List:[a, b, c, d]
Ognl初始化Map:{a=aa, b=bb, c=cc, d=dd}
通过Ognl访问数组中的元素:xu
通过Ognl访问集合中的元素:liu
通过Ognl访问Map中的元素 :liu
注意点
1.创建集合不用加#,创建map要加#。
2.创建类的一个对象,要使用类的完整路径。
3.要创建带有初始化值的指定类型的List或Map,可以这样#@java.util.TreeMap@{‘key’:’value’,’key’:’value’,……}。
OGNL还有其他用法。这里不再细说。通过上面的例子,我们可以看出,OGNL大概作用是什么:就是用来获取对象的属性和方法。
记住OGNL的表达式、根对象、上下文OgnlContext.
https://blog.csdn.net/a_helloword/article/details/80432364-----参考博客
作者:全网第一菜
来源:CSDN
原文:https://blog.csdn.net/a_helloword/article/details/80432364
原文:https://www.cnblogs.com/beilou310/p/10636184.html