OGNL表达式语言详解
来源:互联网 发布:c语言简单游戏程序代码 编辑:程序博客网 时间:2024/06/05 15:57
众所周知,OGNL充斥在Struts2前后台数据传递与存储的方方面面,给Struts2中数据的处理带来了极大的方便,所以,本次打算以两篇博客来介绍OGNL,第一篇就是脱离MVC框架,单纯介绍OGNL的一般用法和语法,在第二篇博客里面,介绍OGNL的实际应用,本篇是第一篇,以介绍OGNL的语法和一般用法为主;
OGNL(Object-Graph Navigation Language的简称),对象图导航语言,它是一门表达式语言,除了用来设置和获取Java对象的属性之外,另外提供诸如集合的投影和过滤以及lambda表达式等,那么我们先来开启第一个例子,首先新建一个Java Project,由于OGNL是Apache开源项目的子项目,所以需要额外导入两个jar,分别为:ognl-x.x.xx.jar和javassist-x.x.xx.jar,搭建完毕后项目结构如下:
接下来给大家展示两个JavaBean类,整个OGNL的介绍,将围绕着这两个类展开
[html] view plain copy
package com.ognl.domain;
import java.util.HashSet;
import java.util.Set;
public class SlDept implements java.io.Serializable {
private static final long serialVersionUID = 3537237434024057830L; private String name; private Set<SlEmployee> slEmployees = new HashSet<SlEmployee>(0); public SlDept() { } public String getName() { return name; } public void setName(String name) { this.name = name; } public Set<SlEmployee> getSlEmployees() { return slEmployees; } public void setSlEmployees(Set<SlEmployee> slEmployees) { this.slEmployees = slEmployees; }
}
[html] view plain copy
package com.ognl.domain;
public class SlEmployee implements java.io.Serializable {
private static final long serialVersionUID = 4873217019660076767L; private SlDept slDept; private String name; public SlEmployee() { } public SlDept getSlDept() { return slDept; } public void setSlDept(SlDept slDept) { this.slDept = slDept; } public String getName() { return name; } public void setName(String name) { this.name = name; }
}
下面编写一个类,代码如下:
[html] view plain copy
package com.ognl.test;
import com.ognl.domain.SlDept;
import com.ognl.domain.SlEmployee;
import ognl.Ognl;
import ognl.OgnlContext;
import ognl.OgnlException;
public class OgnlTest {
public static void main(String[] args) throws OgnlException { // 新建一个部门对象并设置部门名称 SlDept dept = new SlDept(); dept.setName("销售部"); // 新建一个员工对象并设置员工姓名 SlEmployee emp = new SlEmployee(); emp.setName("张三"); // 构建一个OgnlContext对象 OgnlContext context = new OgnlContext(); // 将上述部门和员工对象放入Ognl上下文环境中 context.put("dept", dept); context.put("emp", emp); // 将员工设置为根对象 context.setRoot(emp); // 构建Ognl表达式的树状表示,用来获取 Object expression = Ognl.parseExpression("#dept.name"); // 解析树状表达式,返回结果 Object deptName = Ognl.getValue(expression, context, context.getRoot()); System.out.println(deptName); }
}
最终输出结果为销售部,需要注意的是看到上述的”#”是不是特别眼熟,对在Struts2中特别常见,而且大家应该发现所谓的对象图导航语言指的就是通过 “放置到OgnlContext中的名字.属性名字” 的方式去获取对应对象的属性值;
首先介绍一下Ognl中,常用到的两个类:
ognl.Ognl类:这个类主要用来解析和解释执行Ognl表达式
ognl.OgnlContext类:这个类为Ognl表达式提供了一个执行环境,这个类实现了Map接口,所以允许通过put(key,obj)方法向OgnlContext环境中方式各种类型的对象,需要注意的是在OgnlContext中对象分为两种,第一种是叫做root对象(根对象),在整个OgnlContext中有且最多只能有一个根对象,可以通过调用OgnlContext.setRoot(obj)设置为根对象,另外一种就是OgnlContext中的普通对象,这种个数类型不受限制,那么既然分为两种方式,肯定在获取对象属性的方式上是有所不同的,下面通过代码比较下:
1、获取普通对象的属性值方式;
比如上述例子当中,dept对象就是放置到OgnlContext中的普通对象,对于这种普通对象,只能通过“#dept.name”的方式去获取属性值,需要注意的是dept指的是放置到上下文中key的值,另外在Dept类型中要提供getName方法;
2、获取根对象的属性值的方式,有两种,第一种也是跟上述方式一样,不多做叙述
[html] view plain copy
Object expression = Ognl.parseExpression(“#emp.name”);
第二种,直接写属性名称就可以,注意:这个时候就不要加“#”,如下
[html] view plain copy
expression = Ognl.parseExpression(“name”);
原理是这样的,如果Ognl在解析表达式的时候发现表达式开头带有”#”,会去普通对象中,去寻找,如果没有”#”,则会默认去根对象中去寻找,由于根对象只有一个,所以只需要属性名字
综合上述两种方式,通过一个直观的例子,理解一下:
[html] view plain copy
package com.ognl.test;
import com.ognl.domain.SlDept;
import com.ognl.domain.SlEmployee;
import ognl.Ognl;
import ognl.OgnlContext;
import ognl.OgnlException;
public class OgnlTest {
public static void main(String[] args) throws OgnlException { // 新建一个部门对象并设置部门名称 SlDept dept = new SlDept(); dept.setName("软件开发部"); // 新建一个员工对象并设置员工姓名 SlEmployee emp = new SlEmployee(); emp.setName("李四"); emp.setSlDept(dept); // 构建一个OgnlContext对象 OgnlContext context = new OgnlContext(); // 将上述部门和员工对象放入Ognl上下文环境中 context.put("dept", dept); context.put("emp", emp); // 将员工设置为跟对象 context.setRoot(emp); // 从普通对象中直接获取部门名称 Object expression = Ognl.parseExpression("#dept.name"); Object deptName = Ognl.getValue(expression, context, context.getRoot()); System.out.println(deptName); System.out.println("-------------------------------------------"); // 间接获取部门名称 expression = Ognl.parseExpression("#emp.slDept.name"); deptName = Ognl.getValue(expression, context, context.getRoot()); System.out.println(deptName); System.out.println("-------------------------------------------"); // 从根对象中直接获取部门名称 expression = Ognl.parseExpression("slDept.name"); deptName = Ognl.getValue(expression, context, context.getRoot()); System.out.println(deptName); }
}
通过例子可以发现,咱们主要工作就是用来学习如何让表达式合法,能够被正确解析且解释执行就可以了;
下面,相信通过上面的例子,我们对Ognl表达式有了一个认识,下面开始学习如何在Ognl表达式用调用方法,大家都知道方法分为静态方法和非静态方法,好的,看例子:
[html] view plain copy
package com.ognl.test;
import com.ognl.domain.SlDept;
import com.ognl.domain.SlEmployee;
import ognl.Ognl;
import ognl.OgnlContext;
import ognl.OgnlException;
public class OgnlTest2 {
public static void main(String[] args) throws OgnlException { // 新建一个部门对象并设置部门名称 SlDept dept = new SlDept(); dept.setName("上海-软件技术支持部"); // 新建一个员工对象并设置员工姓名 SlEmployee emp = new SlEmployee(); emp.setName("李小龙"); emp.setSlDept(dept); emp.setAge("22"); // 构建一个OgnlContext对象 OgnlContext context = new OgnlContext(); // 将上述部门和员工对象放入Ognl上下文环境中 context.put("dept", dept); context.put("emp", emp); // 将员工设置为跟对象 context.setRoot(emp); // 从根对象中直接获取部门名称长度,非静态方法 Object expression = Ognl.parseExpression("slDept.name.length()"); Object length = Ognl.getValue(expression, context, context.getRoot()); System.out.println(length); // 在Ognl表达式中使用静态方法 expression = Ognl.parseExpression("@java.lang.Integer@valueOf(age)"); length = Ognl.getValue(expression, context, context.getRoot()); System.out.println(length); }
}
第三、接下来介绍,Ognl表达式中如何处理数组、集合和Map对象
[html] view plain copy
package com.ognl.test;
import java.util.ArrayList;
import java.util.List;
import ognl.Ognl;
import ognl.OgnlContext;
import ognl.OgnlException;
public class OgnlTest3 {
public static void main(String[] args) throws OgnlException { OgnlContext context = new OgnlContext(); // 通过Ognl表达式构建一个LinkedList对象,这注意:一定是包名+类名的形式 Object list = Ognl.parseExpression("new java.util.LinkedList()"); Object obj = Ognl.getValue(list, context, context.getRoot()); System.out.println(obj); System.out.println("----------------------------"); // 在Ognl中提供了一种类似数组索引的方式访问集合指定位置的元素 // 下述例子直接构建了一个包含aa, bb, cc, dd四个元素的集合,然后访问集合中的第三个元素 Object object15 = Ognl.getValue("{'aa', 'bb', 'cc', 'dd'}[2]", context, context.getRoot()); System.out.println(object15); System.out.println("----------------------------"); // 处理数组类型 String[] strs = new String[] { "aa", "bb", "cc" }; context.put("strs", strs); System.out.println(Ognl.getValue("#strs[1]", context, context.getRoot())); System.out.println("----------------------------"); // 处理集合类型 List<String> words = new ArrayList<String>(); words.add("hello"); words.add("world"); words.add("hello world"); context.put("words", words); System.out.println(Ognl.getValue("#words[0]", context, context.getRoot())); System.out.println("----------------------------"); // 处理Map类型,注意的是为了与集合区分开,在大括号前面加"#" System.out.println( Ognl.getValue("#{'key1': 'value1', 'key2': 'value2', 'key3': 'value3', 'key4': 'value4'}['key3']", context, context.getRoot())); }
}
第四、下面介绍Ognl中的过滤和投影两个概念,简单介绍下,无论过滤还是投影都是针对于数组、集合和Map而言的;
过滤指的是将原集合中不符合条件的对象过滤掉,然后将满足条件的对象,构建一个新的集合对象返回,Ognl过滤表达式的写法是:collection.{?|^|$ expression};
投影指的是将原集合中所有对象的某个属性抽取出来,单独构成一个新的集合对象返回,基础语法为 :collection.{expression};
示例代码如下:
[html] view plain copy
package com.ognl.domain;
public class Student {
private String name; private int age; private double height; public Student() { super(); } public Student(String name, int age, double height) { super(); this.name = name; this.age = age; this.height = height; } 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; } public double getHeight() { return height; } public void setHeight(double height) { this.height = height; } @Override public String toString() { return "Student [name=" + name + ", age=" + age + ", height=" + height + "]"; }
}
[html] view plain copy
package com.ognl.test;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import com.ognl.domain.Student;
import ognl.Ognl;
import ognl.OgnlContext;
import ognl.OgnlException;
public class OgnlTest4 {
public static void main(String[] args) throws OgnlException { Student s1 = new Student("Tom", 22, 170.3); Student s2 = new Student("Jack", 21, 176.2); Student s3 = new Student("Tomas", 23, 180.1); Student s4 = new Student("Lucy", 20, 163.3); List<Student> stus = new ArrayList<Student>(); Collections.addAll(stus, s1, s2, s3, s4); // 新建OgnlContext对象 OgnlContext context = new OgnlContext(); context.put("stus", stus); // 过滤(filtering),collection.{? expression} // 利用过滤获取身高在175以上的所有学生集合 // 输出结果:[Student [name=Jack, age=21, height=176.2], Student [name=Tomas, age=23, height=180.1]] System.out.println(Ognl.getValue("#stus.{? #this.height > 175.0}", context, context.getRoot())); // 过滤(filtering),collection.{^ expression} // 利用过滤获取身高在175以上的所有学生集合中第一个元素 // 输出结果:[Student [name=Jack, age=21, height=176.2]] System.out.println(Ognl.getValue("#stus.{^ #this.height > 175.0}", context, context.getRoot())); // 过滤(filtering),collection.{$ expression} // 利用过滤获取身高在175以上的所有学生集合的最后一个元素 // 输出结果:[Student [name=Tomas, age=23, height=180.1]] System.out.println(Ognl.getValue("#stus.{$ #this.height > 175.0}", context, context.getRoot())); // 投影(projection), collection. {expression} // 获取集合中的所有学生的姓名 // 输出结果:[Tom, Jack, Tomas, Lucy] System.out.println(Ognl.getValue("#stus.{name}", context, context.getRoot())); }
}
本篇博客从Ognl中对java对象属性值的访问,静态和非静态方法的调用,Ognl如何处理数组、集合和Map类型的数据以及集合的投影、过滤等几个方面介绍了日常用到的OGNL知识,这是基础,但却又是最关键的东西,牢记!
- OGNL表达式语言详解
- OGNL表达式语言详解
- OGNL表达式语言介绍
- OGNL表达式语言介绍
- OGNL表达式语言
- OGNL表达式语言介绍
- OGNL表达式语言
- ognl表达式语言
- 六、OGNL表达式语言
- OGNL表达式语言
- OGNL表达式语言学习
- OGNL表达式语言1
- OGNL表达式语言
- OGNL表达式语言
- OGNL表达式语言(一)
- 国际化、OGNL表达式语言
- OGNL表达式语言学习
- OGNL表达式语言
- 《剑指offer》刷题笔记(数组):二维数组中的查找
- 汇编语言——学习资料(更新........)
- ABAP 友情链接
- css预处理器
- 西南交通大学第十三届校赛 HMagic Maze DFS
- OGNL表达式语言详解
- 传统JDBC以及MyBatis和Hibernate的对比
- VS2010上安装配置ARToolKitPlus
- 数组指针和指针数组的区别
- 【ccf-201409-1】相邻数对
- 初学javaweb,我选择存储过程——MySql存储过程详解
- 【小白学CV】传统特征点检测算法SIFT详细分析
- table 删除内容
- Remove Duplicates from Sorted Array