OGNL详解

OGNL(Object-Graph Navigation Language)是一种强大的表达式语言,常用于Struts框架。它支持字符串、字符、数字、布尔值和null常量。属性引用针对不同类型的对象有不同的处理方式,如Map、数组和普通对象。OGNL还允许方法调用、索引访问、变量引用、数组和List创建、Map创建以及条件和逻辑运算。此外,它还支持集合投影、选择以及对Java集合的特殊属性访问。OGNL的表达式求值规则与Java有所不同,如逗号用于分隔参数,大括号表示集合,'in'操作符用于类型转换等。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

概述

OGNL是Object Graphic Navigation Language(对象图导航语言)的缩写,他是一个开源项目。Struts框架使用OGNL作为默认的表达式语言。

基本上已停止维护。

详解

语法

表达式

常量

OGNL有下列的种类的常量:

  1. 字符串,就像在java中一样:由单引号或双引号界定,带有全套的字符转义
  2. 字符,也像在java中一样:由单引号界定,带有全套的字符转义
  3. 数字,比在java中多一些种类。除了java的ints,longs,floats,doubles,OGNL让你指定BigDecimal(大小数的)用一个“b“或“B”后缀,和BigIntegers(大整数)以一个“h“或”H“后缀。(考虑”huge“—我们选择”h“用于大整数因为它不会和16进制数冲突)
  4. 布尔(true和false)
  5. null值
//1:
//2:
//3:
//4:
//5:

属性引用

OGNL对不同的类型有不同的处理属性引用方式。Map会把所有的属性引用作为查询或存储,name作为key。列表和数组对待数字属性是相似的,属性名作为索引,但是字符串属性的工作方式跟ordinary对象相似。Ordinary对象(也就是全部的其他种类)仅仅能处理字符串属性和这样做通过使用“get“和“set”方法(或者“is”和“set”),如果对象有它们的话,或者一个字段带有被给予的名字。

属性“name”可以是任何类型,不仅仅是字符串。但是想引用非字符串的属性,必须使用之前称为“index”的符号。

例如,想要获得数组长度,你可以使用这个表达式

array.length

但是,想要获得数组的元素0,你必须使用一个表达式像这样:

array[0]

注意java集合有一些特殊的属性和他们关联。

索引

indexing符号实际上就是属性引用。

“array.length” 表达式完全等同:

array["length"]
//下面这个表达式返回相同的值。
array["len" + "gth"]

数组和List索引

Java arrays 和Lists的索引很简单,就想Java中使用一样。一个int 索引返回一个元素引用,如果index超出边界,仍会抛出IndexOutOfBoundsException

JavaBeans索引属性

JavaBeans支持通过索引获取属性,意味着一个object有以下类似的方法集:

public PropertyType[] getPropertyName();
public void setPropertyName(PropertyType[] anArray);
public PropertyType getPropertyName(int index);
public void setPropertyName(int index, PropertyType value);

OGNL能够翻译并且提供无缝的通过index符号访问属性。例如:

someProperty[2]

能够自动的路由到正确的indexed property accessorgetSomeProperty(2)`` 、setSomeProperty(2, value)`)

OGNL 对象索引属性

OGNL扩展了索引属性,包括索引任何对象的属性,不只是JavaBeans的整形索引属性。OGNL通过pattern来查找method来索引属性。

public PropertyType getPropertyName(IndexType index);
public void setPropertyName(IndexType index, PropertyType value);

IndexTypePropertyType必须和getset方法匹配才。例如session

public Object getAttribute(String name) 
public void setAttribute(String name, Object value)

OGNL表示可以get和set一个attribute:

session.attribute["foo"]

方法调用

OGNL的方法调用和Java有些不同,OGNL在运行时,必须在没有额外的实际参数的类型信息的情况能够选择正确的方法。OGNL会选择与提供类型最匹配的方法,如果存在多个方法匹配,则随机选择一个。

特殊情况,null匹配所有的非原生类型,可能会返回一个非期望的方法。

注意,逗号用于分隔参数,逗号除非包含在括号内否则不能使用。例如:

//匹配2个参数的方法
method( ensureLoaded(), name )
//匹配1个参数的方法
method( (ensureLoaded(), name) )

变量引用

OGNL有一个简单的变量模式,他能够定义一个变量用来保存结果,并在后面引用。所有OGNL变量在整个表达式中是全局的,引用一个变量,在它的名字前加#,例如:

#var

OGNL通过this变量引用当前对象。例如:

//this代表的 size()返回的值。
listeners.size().(#this > 100? 2*#this : 20+#this)

变量赋值

#var = 99

括号表达式

在圆括号内的表达式被作为一个单元计算。能够提高表达式的优先级。

括号表达式中,如果有逗号,则整个表达式的返回值是最后一个逗号右边的表达式的值。

链式子表达式

当使用点(.)之后的括号表达式,在括号内的表达式中,点之前的对象会做为整个表达式的当前对象(this)。

//name表达式返回的是parent.name 。计算过程中会计算ensureLoaded()。整个表达式返回 parent.name的值。
headline.parent.(ensureLoaded(), name)
  

集合构建

Lists
name in { null,"Untitled" }
原生数组
new int[] { 1, 2, 3 }
new int[5]
maps
#{ "foo" : "foo value", "bar" : "bar value" }
//指定类型
#@java.util.LinkedHashMap@{ "foo" : "foo value", "bar" : "bar value" }

集合投影

listeners.{delegate}
objects.{ #this instanceof String ? #this : #this.toString()}

选择

listeners.{? #this instanceof ActionListener}   // 注意问号
//选择第一个元素
objects.{^ #this instanceof String }
//选择最后一个元素
objects.{$ #this instanceof String }

调用构造函数

使用new,指定fullname。

new java.util.ArrayList()

调用静态方法

 @class@method(args)
 //如果没有指定类,默认是java.lang.Math
 

获取静态字段

@class@field

表达式求值

如果一个括号表达式,在前面没有点号(.),第一个表达式的结果会。括号表达式的结果会作为root对象,


伪lambda

#fact = :[#this<=1? 1 : #this*#fact(#this-1)], #fact(30H)  //注意中括号。

集合的伪属性

CollectionSpecial Properties
Collection (inherited by Map, List & Set)size: The size of the collectionisEmpty: Evaluates to true if the collection is empty
Listiterator: Evalutes to an Iterator over the List.
Mapkeys: Evalutes to a Set of all keys in the Map``values: Evaluates to a Collection of all values in the MapNote These properties, plus size and isEmpty, are different than the indexed form of access for Maps (i.e. someMap["size"] gets the "size" key from the map, whereas someMap.size gets the size of the Map
Setiterator: Evalutes to an Iterator over the Set
Iteratornext: Evalutes to the next object from the Iterator``hasNext: Evaluates to true if there is a next object available from the Iterator
Enumerationnext: Evalutes to the next object from the Enumeration``hasNext: Evaluates to true if there is a next object available from the Enumeration``nextElement: Synonym for next``hasMoreElements: Synonym for hasNext

与Java操作符差异

逗号分隔符

最后一个表达式的值作为整个表达式的结果

大括号

数组,集合

in

强制类型转换

转换为boolean
  • boolean:直接转换
  • 数字:非0为true,0为false。
  • 字符:为0为true
  • 其他:非null 为true
转换为数字
转换为整形
转换为集合

高级开发

附录

参考:http://commons.apache.org/proper/commons-ognl/language-guide.html

操作符

OperatorgetValue() NotessetValue() Notes
e1, e2
Sequence operator
Both e1 and e2 are evaluated with the same source object, and the result of e2 is returned.getValue is called on e1, and then setValue is called on e2.
e1 = e2
Assignment operator
getValue is called on e2, and then setValue is called on e1 with the result of e2 as the target object.Cannot be the top-level expression for setValue.
e1 ? e2 : e3
Conditional operator
getValue is called on e1 and the result is interpreted as a boolean. getValue is then called on either e2 or e3, depending on whether the result of e1 was true or false respectively, and the result is returned.getValue is called on e1, and then setValue is called on either e2 or e3.
e1 || e2, e1 or e2
Logical or operator
getValue is called on e1 and the result is interpreted as a boolean. If true, that result is returned; if false, getValue is called on e2 and its value is returned.getValue is called on e1; if false, setValue is called on e2. Note that e1 being true prevents any further setting from taking place.
e1 && e2, e1 and e2
Logical and operator
getValue is called on e1 and the result is interpreted as a boolean. If false, that result is returned; if true, getValue is called on e2 and its value is returned.getValue is called on e1; if true, setValue is called on e2. Note that e1 being false prevents any further setting from taking place.
e1 | e2, e1 bor e2
Bitwise or operator
e1 and e2 are interpreted as integers and the result is an integer.Cannot be the top-level expression passed to setValue.
e1 ^ e2, e1 xor e2
Bitwise exclusive-or operator
e1 and e2 are interpreted as integers and the result is an integer.Cannot be the top-level expression passed to setValue.
e1 & e2, e1 band e2
Bitwise and operator
e1 and e2 are interpreted as integers and the result is an integer.Cannot be the top-level expression passed to setValue.
e1 == e2, e1 eq e2
Equality test
e1 != e2, e1 neq e2
Inequality test
Equality is tested for as follows. If either value is null, they are equal if and only if both are null. If they are the same object or the equals() method says they are equal, they are equal. If they are both Numbers, they are equal if their values as double-precision floating point numbers are equal. Otherwise, they are not equal. These rules make numbers compare equal more readily than they would normally, if just using the equals method.Cannot be the top-level expression passed to setValue.
e1 < e2, e1 lt e2
Less than comparison
e1 <= e2, e1 lte e2
Less than or equals comparison
e1 > e2, e1 gt e2
Greater than comparison
e1 >= e2, e1 gte e2
Greater than or equals comparison
e1 in e2
List membership comparison
e1 not in e2
List non-membership comparison
The ordering operators compare with compareTo() if their arguments are non-numeric and implement Comparable; otherwise, the arguments are interpreted as numbers and compared numerically. The in operator is not from Java; it tests for inclusion of e1 in e2, where e2 is interpreted as a collection. This test is not efficient: it iterates the collection. However, it uses the standard OGNL equality test.Cannot be the top-level expression passed to setValue.
e1 << e2, e1 shl e2
Bit shift left
e1 >> e2, e1 shr e2
Bit shift right
e1 >>> e2, e1 ushr e2
Logical shift right
e1 and e2 are interpreted as integers and the result is an integer.Cannot be the top-level expression passed to setValue.
e1 + e2
Addition
e1 - e2
Subtraction
The plus operator concatenates strings if its arguments are non-numeric; otherwise it interprets its arguments as numbers and adds them. The minus operator always works on numbers.Cannot be the top-level expression passed to setValue.
e1* e2
Multiplication
e1 / e2
Division
e1 % e2
Remainder
Multiplication, division, which interpret their arguments as numbers, and remainder, which interprets its arguments as integers.Cannot be the top-level expression passed to setValue.
+ e
Unary plus
- e
Unary minus
! e, not e
Logical not
~ e
Bitwise not
e instanceof class
Class membership
Unary plus is a no-op, it simply returns the value of its argument. Unary minus interprets its argument as a number. Logical not interprets its argument as a boolean. Bitwise not interprets its argument as an integer. The class argument to instanceof is the fully qualified name of a Java class.Cannot be the top-level expression passed to setValue.
e.method(args)
Method call
e.property
Property
e1[ e2 ]
Index
e1.{ e2 }
Projection
e1.{? e2 }
Selection
e1.(e2)
Subexpression evaluation
e1(e2)
Expression evaluation
Generally speaking, navigation chains are evaluated by evaluating the first expression, then evaluating the second one with the result of the first as the source object.Some of these forms can be passed as top-level expressions to setValue and others cannot. Only those chains that end in property references (e.property), indexes (e1[e2]), and subexpressions (e1.(e2)) can be; and expression evaluations can be as well. For the chains, getValue is called on the left-hand expression (e or e1), and then setValue is called on the rest with the result as the target object.
constant
Constant
( e )
Parenthesized expression
method(args)
Method call
property
Property reference
[ e ]
Index reference
{ e,}
List creation
#variable
Context variable reference
@class@method(args)
Static method reference
@class@field
Static field reference
new class(args)
Constructor call
new array-component-class[] { e,}
Array creation
#{ e1 : e2,}
Map creation
#@classname@{ e1 : e2,}
Map creation with specific subclass
:[ e ]
Lambda expression definition
Basic expressionsOnly property references (property), indexes ([e]), and variable references (#variable) can be passed as top-level expressions to setValue. For indexes, getValue is called on e, and then the result is used as the property “name” (which might be a String or any other kind of object) to set in the current target object. Variable and property references are set more directly.
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值