众所周知,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的介绍,将围绕着这两个类展开

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;}}
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;}}

下面编写一个类,代码如下:

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、获取根对象的属性值的方式,有两种,第一种也是跟上述方式一样,不多做叙述

Object expression = Ognl.parseExpression("#emp.name");

第二种,直接写属性名称就可以,注意:这个时候就不要加“#”,如下

expression = Ognl.parseExpression("name");

原理是这样的,如果Ognl在解析表达式的时候发现表达式开头带有"#",会去普通对象中,去寻找,如果没有"#",则会默认去根对象中去寻找,由于根对象只有一个,所以只需要属性名字

综合上述两种方式,通过一个直观的例子,理解一下:

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表达式用调用方法,大家都知道方法分为静态方法和非静态方法,好的,看例子:

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对象

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};

示例代码如下:

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;}@Overridepublic String toString() {return "Student [name=" + name + ", age=" + age + ", height=" + height + "]";}
}
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知识,这是基础,但却又是最关键的东西,牢记!

以上转自https://blog.csdn.net/yu102655/article/details/52179695

OGNL表达式语言详解相关推荐

  1. java ognl表达式 与struts2标签_Struts2 OGNL表达式实例详解

    Object Graph Navigation Language:对象图导航语言,就是用点来访问成员变量 例1: struts.xml: /ognl.jsp OgnlAction1.java: pac ...

  2. Java Web----EL(表达式语言)详解

    博文连接  Java Web中的EL(表达式语言)详解 表达式语言(Expression Language)简称EL,它是JSP2.0中引入的一个新内容.通过EL可以简化在JSP开发中对对象的引用,从 ...

  3. Struts2中的OGNL表达式的详解

    首先了解下OGNL的概念: OGNL是Object-Graph Navigation Language的缩写,全称为对象图导航语言,是一种功能强大的表达式语言,它通过简单一致的语法,可以任意存取对象的 ...

  4. 克鲁斯卡尔算法c语言,Kruskal算法(一)之 C语言详解

    最小生成树 在含有n个顶点的连通图中选择n-1条边,构成一棵极小连通子图,并使该连通子图中n-1条边上权值之和达到最小,则称其为连通网的最小生成树. 例如,对于如上图G4所示的连通网可以有多棵权值总和 ...

  5. 有向图邻接矩阵c语言编程,邻接矩阵有向图(一)之 C语言详解

    本章介绍邻接矩阵有向图.在"图的理论基础"中已经对图进行了理论介绍,这里就不再对图的概念进行重复说明了.和以往一样,本文会先给出C语言的实现:后续再分别给出C++和Java版本的实 ...

  6. 邻接矩阵用c语言,邻接矩阵无向图(一)之 C语言详解

    本章介绍邻接矩阵无向图.在"图的理论基础"中已经对图进行了理论介绍,这里就不再对图的概念进行重复说明了.和以往一样,本文会先给出C语言的实现:后续再分别给出C++和Java版本的实 ...

  7. Drools 规则语言详解(上)

    http://www.blogjava.net/guangnian0412/archive/2006/06/09/51574.html http://www.blogjava.net/guangnia ...

  8. JSP 中EL表达式用法详解

    EL 全名为Expression Language EL 语法很简单,它最大的特点就是使用上很方便.接下来介绍EL主要的语法结构: ${sessionScope.user.sex} 所有EL都是以${ ...

  9. c++指针详解_c语言详解sizeof

    一.sizeof的概念 sizeof是C语言的一种单目操作符,如C语言的其他操作符++.--等. 它并不是函数. sizeof操作符以字节形式给出了其操作数的存储大小. 操作数可以是一个表达式或括在括 ...

  10. Spring EL表达式使用详解

    Spring EL表达式使用详解 什么是Spring EL表达式 注入字面值 注入操作系统(OS)的属性 注入properties配置文件中数据 Bean属性调用 Bean方法调用 T运算符 构造器 ...

最新文章

  1. jenkins 手动执行_Jenkins(一)
  2. django 日志配置
  3. 有关UITableView--cell复用问题
  4. 学习 (2012.01)
  5. 阅读笔记-游戏开发中的人工智能-第3章-移动模式
  6. kmalloc参数GFP_ATOMIC or GFP_KERNEL?
  7. 其实,前面倒腾那么多,只是为了想玩SPRING BOOT
  8. SE 2.4.0 patch机器码笔记
  9. SQLMAP注入拖库过程 1
  10. Java如何实现代理服务器?
  11. WSO2 ESB 5.0.0 集群配置
  12. c语言 步进电机 程序,步进电机加速启动C语言程序
  13. java扫码枪键盘_JAVA读取USB扫描枪
  14. WIN10REALTEL高清音频管理器如何调音?调音无效怎么办?
  15. 摄影基础知识——光学变焦和数码变焦
  16. Win32Forth初学者指导-前言
  17. IIS 发生意外错误 0x8ffe2740
  18. 尚硅谷前端框架vue语法(二)
  19. 计算机基础知识-进制的运算
  20. AUTOCAD——快速标注命令

热门文章

  1. PHP开源旅游网站程序,PHP开源旅游网站源码下载
  2. 推荐几款常用的Socks5代理软件
  3. Foobar音乐播放器——最佳音乐播放器 - imsoft.cnblogs
  4. cd linux制作u盘启动盘,小编详解cdlinux u盘启动如何制作
  5. 自己做量化交易软件(32)小白量化实战6--仿通达信公式选股
  6. T410s主板上的黑色塑料是散热问题的祸首
  7. java程序员面试真题及详解2017(纯手动)
  8. rubyonrails test 小记
  9. 向Richedit插入动态Gif的实现(关于QQ表情功能的制作)
  10. 未能连接驱动人生服务器怎么解决,重装系统后无法上网?驱动人生提供3个解决方案...