概述
OGNL是Object Graphic Navigation Language(对象图导航语言)的缩写,他是一个开源项目。Struts框架使用OGNL作为默认的表达式语言。
基本上已停止维护。
详解
语法
表达式
常量
OGNL有下列的种类的常量:
- 字符串,就像在java中一样:由单引号或双引号界定,带有全套的字符转义
- 字符,也像在java中一样:由单引号界定,带有全套的字符转义
- 数字,比在java中多一些种类。除了java的ints,longs,floats,doubles,OGNL让你指定BigDecimal(大小数的)用一个“b“或“B”后缀,和BigIntegers(大整数)以一个“h“或”H“后缀。(考虑”huge“—我们选择”h“用于大整数因为它不会和16进制数冲突)
- 布尔(true和false)
- 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 accessor
(getSomeProperty(2)`` 、
setSomeProperty(2, value)`)
OGNL 对象索引属性
OGNL扩展了索引属性,包括索引任何对象的属性,不只是JavaBeans的整形索引属性。OGNL通过pattern
来查找method
来索引属性。
public PropertyType getPropertyName(IndexType index);
public void setPropertyName(IndexType index, PropertyType value);
IndexType
和PropertyType
必须和get
和set
方法匹配才。例如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) //注意中括号。
集合的伪属性
Collection | Special Properties |
---|---|
Collection (inherited by Map , List & Set ) | size : The size of the collectionisEmpty : Evaluates to true if the collection is empty |
List | iterator : Evalutes to an Iterator over the List . |
Map | keys : Evalutes to a Set of all keys in the Map``values : Evaluates to a Collection of all values in the Map Note These properties, plus size and isEmpty , are different than the indexed form of access for Map s (i.e. someMap["size"] gets the "size" key from the map, whereas someMap.size gets the size of the Map |
Set | iterator : Evalutes to an Iterator over the Set |
Iterator | next : Evalutes to the next object from the Iterator``hasNext : Evaluates to true if there is a next object available from the Iterator |
Enumeration | next : 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
操作符
Operator | getValue() Notes | setValue() 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 Number s, 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 expressions | Only 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. |