Ognl全称Object Graph Navigation Language,是Apache Commons下的一个子项目。和JSP中的EL表达式一样,通常作为View层访问数据的一种方式。但是OGNL的功能比EL表达式功能强大的多(看完这篇文章后你会觉得OGNL能把EL表达式秒成渣)
jar包下载
使用ognl最有名的项目就是Struts2和MyBatis了,关于OGNL在Struts2中的使用以及原理,后面会有一篇文章详细说明。
这里的例子不会依赖Struts2的运行环境。
官网下载地址:
http://commons.apache.org/proper/commons-ognl/download_ognl.cgi
Maven依赖:
1 | <!-- https://mvnrepository.com/artifact/ognl/ognl --> |
基本语法
最基本的语法很简单:通过属性(property)来访问Bean的数据,所以OGNL要求类对象具有getter/setter方法(也就是符合标准JavaBean的规则)。
下面的例子中将会使用User类作为测试的JavaBean
1 | public class User { |
下面的例子中会经常用到Ognl类的两个方法(暂时不了解这两个方法有什么作用不要紧,后面用到的时候自然就明白):
1 | /** |
root对象
使用ognl表达式访问root元素对象中的属性不需要任何前缀。
root对象属性访问:
1 |
|
对象的访问方式和Map的一样
对象方法调用:
1 |
|
数组索引:
1 |
|
context上下文
使用OGNL表达式访问context中的元素需要添加#符号作为前缀,而且context需要是Map接口的实现类。同时要求添加一个root对象,此时root对象会以"root"字符串做为Key添加到context中。
1 |
|
事实上使用
Object value = Ognl.getValue("username", user);方式,不指定context,它会默认帮你创建一个OgnlContext,OgnlContext也实现了Map接口。而使用Object value = Ognl.getValue("#names[1]", context, users);方式,指定的map类型的context,最终也会被转换成OgnlContext。
通过查看OgnlContext源码,会发现有几个关键点:
1 | public class OgnlContext extends Object implements Map |
OGNL中的常量
**1.**字符串常量,需要用引号引起来(可以是单引号也可以是双引号,单引号可以作为内嵌脚本使用)。
**2.**字符常量,需要用单引号引起来
**3.**数值常量,支持Java的int,long,float,double。同时可以使用”b” 或 “B”作为后缀表示BigDecimal类型的数据,使用”h” 或 “H”作为后缀表示BigInteger类型的数据(这里的h表示huge,这个不会干扰16进制的数字)
**4.**布尔类型,true和false
**5.**空指针,null
集合元素
访问List元素
1 |
|
访问Map元素
1 |
|
Map和对象的访问方式一样:
1 |
|
集合的伪属性
1 |
|
OGNL中为集合相关的类提供了以下的伪属性:
| 集合 | 特殊属性 |
|---|---|
Map, List Set | size: 集合中元素的个数isEmpty: 集合是否为空 |
| List | iterator: 获取list的迭代器 |
| Map | keys: 等价于keys()方法values: 等价于values()方法。注意: 这两个属性以及 size and isEmpty, 和map['size']这种访问方式不同,map['size']会访问key为'size'的元素。 |
| Set | iterator: 获取Set的迭代器 |
| Iterator | next: 获取迭代器的下一个元素hasNext: 迭代器是否有可用元素。 |
| Enumeration | next: 获取迭代器的下一个元素hasNext迭代器是否有可用元素。 |
构造集合
构造原生数组
1 |
|
构造List元素
1 |
|
构造Map集合
1 |
|
使用指定的类构造Map
1 |
|
构造复杂map
1 |
|
使用变量构造map、list或数组
1 |
|
[not] in操作
1 |
|
^、$和?操作符进行元素过滤
也有人把这些操作叫做投影(projection)
1 |
|
三目运算符
1 |
|
类的静态方法调用
1 |
|
多条语句的执行
1 |
|
Lambda表达式
1 |
|
附录:OGNL语法摘要表
| Operator | getValue() Notes | setValue() Notes |
|---|---|---|
e1, e2Sequence operator | Both e1 and e2 are evaluated with the same source object, and the result of e2is returned. | getValue is called on e1, and then setValue is called on e2. |
e1 = e2Assignment 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 : e3Conditional 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*, e1or*e2*<br>Logicalor`operator | |
e1 && e2, e1 and e2Logical andoperator | 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*<br>Bitwiseor`operator | e1 and e2 are interpreted as integers and the result is an integer. |
e1 ^ e2, e1 xor e2Bitwise 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 e2Bitwise 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 e2Equality test e1 != e2, e1 neq e2Inequality 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 e2Less than comparison e1 <= e2, e1 lte e2Less than or equals comparison e1 > e2, e1 gt e2Greater than comparison e1 >= e2, e1 gte e2*Greater than or equals comparison *e1 in e2List membership comparison e1 not in e2List 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 e2Bit shift left e1 >> e2, e1 shr e2Bit shift right e1 >>> e2, e1 ushr e2Logical 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 + e2Addition e1 - e2Subtraction | 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* e2Multiplication e1 / e2Division e1 % e2Remainder | 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. |
+ eUnary plus - eUnary minus ! e, not eLogical not ~ eBitwise not e instanceof classClassmembership | 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 .propertyProperty 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 setValueand 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. |
constantConstant( e )Parenthesized expression method (args)Method call property Property reference [ e ]Index reference { e, … }List creation #variableContext variable reference @class@method(args)Static method reference @class@fieldStatic 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. |
参考文章:
OGNL官方文档:http://commons.apache.org/proper/commons-ognl/language-guide.html

