首页 > 其他分享 >OGNL 基础使用和入门

OGNL 基础使用和入门

时间:2024-02-01 17:25:41浏览次数:20  
标签:group 入门 对象 基础 OGNL users 表达式 name

一、什么是OGNL

OGNL是Object Graph Navigation Language的缩写,中文意思是对象导航图语言。它是一种开源的表达式语言(Expression Language),被集成在Struts2等框架中,主要用于对数据进行访问。它拥有类型转换、访问对象方法、操作集合对象等功能,并可以通过简单的语法存取对象的任意属性,调用对象的方法,遍历整个对象的结构图,实现字段类型转化等功能。

OGNL支持各种纷繁复杂的表达式。但是最最基本的表达式的原型,是将对象的引用值用点串联起来,从左到右,每一次表达式计算返回的结果成为当前对象,后面部分接着在当前对象上进行计算,一直到全部表达式计算完成,返回最后得到的对象。OGNL则针对这条基本原则进行不断的扩充,从而使之支持对象树、数组、容器的访问,甚至是类似SQL中的投影选择等操作。

 

OGML三要素包括:

  1. 根对象(Root Object):OGML表达式的起始点,表示要导航和操作的对象图的根节点。
  2. 上下文(Context):包含了表达式求值过程中使用的变量和对象,可以在表达式中引用。上下文可以是一个Map对象,其中存储了变量名和对应的值。
  3. 表达式(Expression):用于导航和操作对象图的OGML表达式,通过根对象和上下文中的变量来计算和求值。

通过组合根对象、上下文和表达式,可以使用OGML执行各种操作,如取值、设值等。

 

二、OGNL的基本操作

1、访问对象的属性

通过使用“.”(点号)运算符,可以访问对象的属性。

针对OGNL的Root对象的对象树的访问时通过“ . ”(点号)将对象的引用串联起来实现的。通过这种方式,OGNL实际上将一个树形的对象结构转化成一个链式结构的字符串来表达语义。

//获取Root对象中的name属性的值
name
//获取Root对象department属性中name属性的实际值
department.name
//获取Root对象department属性的manager属性中name属性的实际值
department.manager.name

 

2、访问上下文环境的

由于OGNL的上下文是一个Map结构,在OGNL进行计算时可以事先在上下文环境中设置一些参数,并让OGNL将这些参数带入进行计算。有时候也需要对这些上下文环境中的参数进行访问,访问这些参数时,需要通过“#”符号加上链式表达式来进行,从而表示与访问Root对象的区别。如下所示:

// 获取OGNL上下文环境中名为introduction的对象的值
#introduction
// 获取OGNL上下文环境中名为parameters的对象中user对象中名为name的属性的值
#parameters.user.name

 

3、调用对象的方法

通过使用“()”运算符,可以调用对象的方法。通过类似Java的方法调用方式进行,也就是通过“ . ”(点号)加方法名称完成方法调用,甚至可以传递参数。

// 调用Root对象中的group属性中users的size()方法
group.users.size()
// 调用Root对象中group中的containsUser的方法,并将上下文环境中名为requestUser的值作为参数传入
group.containsUser(#requestUser)

 

4、访问静态属性和方法

通过使用“@”符号(@[class]@[field / method] ),可以访问静态属性和方法。例如,假设有一个名为“Person”的类,它具有一个名为“NAME”的静态属性,可以使用“Person.NAME”来访问该属性。

// 访问com.example.core.Resource类中名为ENABLE的属性值
@com.example.core.Resource@ENABLE
// 调用com.example.core.Resource类中名为get的方法
@com.example.core.Resource@get()

 

5、使用操作符进行简单计算

OGNL表达式中能使用的操作符基本与Java里的操作符一样,除了能使用+、-、*、/、++、–、==等操作符之外,还能使用mod、in、not in 等。如下所示:

2 + 4  // 加
'hello' + 'world'  //字符串叠加
5 - 3  // 减
9 / 2  // 除
9 mod 2  // 取模
foo++  //递增
foo == bar  // 等于判断
foo in list  // 是否在容器中

 

6、对数组和容器的访问

OGNL表达式可以支持对数组按照数组下标的顺序进行访问。同样的方法可以用于有序的容器,如ArrayList、LinkedHashSet等。对于Map结构,OGNL支持根据键值进行访问。如下所示:

// 访问Root对象的group属性中users的第一个对象的name属性值
group.users[0].name
// 访问OGNL上下文中名为sessionMap的Map对象中key为currentLogonUser
#sessionMap['currentLogonUser']

 

7、投影与选择

OGNL支持类似于数据库中的投影(projection)和选择(selection)功能

投影操作是指选出集合中每个元素的相同属性组成新的集合,类似于关系数据库的字段操作。投影操作语法为 collection.{XXX} ,其中 XXX 就是这个集合中每个元素的公共属性。

选择就是过滤满足 selection 条件的集合元素,类似于关系数据库的结果集操作。选择操作的语法为: collection.{X YYY} ,其中 X 是一个选择操作符,后面则是选择用的逻辑表达式。选择操作符由三种:

  • ? 选择满足条件的所有元素

  • ^ 选择满足条件的第一个元素

  • $ 选择满足条件的最后一个元素

如下所示:

// 返回Root对象的group属性中users这个集合中所有元素的name构成的集合
group.users.{name}  // 新的以name为元素的集合
// 将group中users这个集合中的元素的code和name用-连接符拼起来构成的字符串集合
group.users.{code + '-' + name}  // 新的以'code-name'为元素的集合
// 返回Root对象的group中users这个集合所有元素中name不为null的元素构成的集合
group.users.{? #this.name != null}  // 过滤后的users集合

 

8、构造对象

OGNL支持直接通过表达式来构造对象。构造的方式主要包括3种:

  • 构造List: 使用 {} ,中间使用“ , ”(逗号)隔开元素的方式来表达列表

  • 构造Map:使用 #{} ,中间使用“ , ”(逗号)隔开键值对,并使用冒号隔开key和value来构造Map

  • 构造对象:直接使用已知对象的构造函数来构造对象

构造对象的方法如下所示:

// 构造一个List
{"green", "red", "blue"}
// 构造一个Map
#{"key1" : "value1", "key2" : "value2", "key3" : "value3"}
// 构造一个java.net.URL对象
new java.net.URL("http://localhost/")

 

构造对象对于表达式语言来说是一个非常强大的功能,OGNL不仅能够直接对容器对象构造提供语法层面的支持,还能够对任意的Java对象提供支持。这样一来就使得OGNL不仅仅具备了数据运算这一简单的功能,同时还被赋予了潜在的逻辑计算功能。

 

9、深入this指针

我们知道,OGNL表达式是以“ . ”(点号)进行串联的一个链式字符串表达式。而这个表达式在进行计算的时候,从左到右,表达式每一次计算返回的结果成为一个临时的“当前对象”,并在此临时对象之上继续进行计算,直到得到计算结果。而这个临时的“当前对象”会被存储在一个叫做this的变量中,这个this变量就称为this指针。

在OGNL表达式中的this指针,无疑指向了当前计算的调用者对应的实例。 需要注意的是,如果试图在表达式中使用this指针,需要在this之前加上“#”,如下面例子:

// 返回group中users这个集合中所有age比3大的元素构成的集合
users.{? #this.age > 3}
// 返回group中users这个集合里的大小+1的值
group.users.size().(#this+ 1)
// 返回Root对象的group中users这个集合所有元素中name不为null的元素构成的集合
group.users.{? #this.name != null}

 

10、有关#符号的三种用途

在之前的要点中已经展示了“#”的几种不同用途。在这里在详细总结为:

  • 加在普通OGNL表达式前面,用于访问OGNL上下文中的变量

  • 使用 #{} 语法动态构建Map

  • 加在 this指针之前,表示对this指针的引用

 

标签:group,入门,对象,基础,OGNL,users,表达式,name
From: https://www.cnblogs.com/r1-12king/p/18001669

相关文章

  • Java并发基础:CyclicBarrier全面解析!
    内容摘要CyclicBarrier的优点在于实现了线程间的相互等待与协同,确保所有线程在达到预定屏障点后才能继续执行,它支持屏障的重复使用,非常适合多轮次的任务同步,此外,CyclicBarrier还允许在屏障点执行特定操作,为复杂的多线程协作提供了便利。核心概念业务场景CyclicBarrier允许一组......
  • 【Kotlin基础】Kotlin的标准函数
    所谓标准函数,就是指Standard.kt文件中定义的函数,任何Kotlin代码都可以自由调用所有标准函数,本文主要讨论下几个常用的标准函数:首先看看直观的对比:传入this传入itreturnlambda的最后一行runletreturnthisapplyalsorun()run()函数是具备接收者的隐式调用(apply()),返回的是lambda的......
  • Python中的基础数据类型:List、Tuple和Dict及其常用用法简析
    在Python编程语言中,基础数据类型是构建程序的基本元素。这些基础数据类型包括List(列表)、Tuple(元组)和Dict(字典)。每种数据类型都有其特定的用途和特性,了解并掌握它们对于编写高效、可维护的Python代码至关重要。本文将深入探讨这三种基础数据类型,并通过代码示例展示它们的常用用法。......
  • Spring的任务执行器(TaskExecutor)入门
    Spring的任务执行器(TaskExecutor)入门在现代的应用程序开发中,异步任务的处理是非常常见的需求。Spring框架提供了任务执行器(TaskExecutor)来处理异步任务,使得开发者能够轻松地实现并发处理和异步操作。本篇博文将介绍Spring的任务执行器,包括其概念、用法和最佳实践。什么是任务执行器......
  • 【操作系统和计网从入门到深入】(八)线程
    复习八·线程1.如何理解线程只要满足,比进程轻量化,cpu内所有线程资源共享,创建维护成本更低等要求,就能叫线程。不同的OS实现方式不同,下面这个是Linux特有的方案。Linux没有给线程重新设计数据结构!什么叫做进程?pcb+地址空间+页表CPU调度的基本单位:线程!2.开始使用pthre......
  • 基础知识
    术语IOPS:每秒发生的输人/输出操作的次数,是数据传输的一个度量方法。对于磁盘的读写,1OPS指的是每秒读和写的次数。吞吐量:评价工作执行的速率,尤其是在数据传输方面,这个术语用于描述数据传输速度(字节/秒或比特/秒)。在某些情况下(如数据库),吞吐量指的是操作的速度(每秒操作数......
  • Java并发基础:Phaser全面解析!
    内容概要Phaser是Java中一个灵活的同步工具,其优点在于支持多阶段的任务拆分与同步,并且能够动态地注册与注销参与者,它提供了丰富的等待与推进机制,使得开发者能够更细粒度地控制线程的协调行为,实现复杂的并行任务处理,相比于其他同步工具,Phaser更加灵活且易于扩展,适用于多种并发场景......
  • HTML基础(网安)
    HTML5骨架DTD<!doctypehtml>doctype表示文档类型,html就是html超文本标记语言html标签整个网页必须被<html></html>包裹,他里面有<head></head>和<body></body>两部分<head></head>:网页的配置<body></body>:网页的正式内容,浏览器可视区域标签有一个属性lang,是英......
  • PHP基础入门
    PHP语法初步PHP是一种运行在服务器端的脚本语言,可以镶嵌到HTML当中PHP代码标记asp标记:<%php代码%>短标记:<?PHP代码?>以上两种基本弃用,须在ini中启用脚本标记:<scriptlanguage="php">php代码</script>标准标记:<?phpphp代码?>php变量变量是用来储存信息的"容器"变......
  • Mysql基础(网安)
    SQL语言入门创建数据库单行注释:##多行注释:/**/createtablet_student(snoint(6),snamevarchar(5),sexchar(1),ageint(3),enterdatedate,classnamevarchar(10),emailvarchar(15));查看表的结构,展示表的详细信息desct_stu......