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 e2 is 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*, e1 or*e2*<br>Logical or`operator | |
e1 && e2, e1 and e2Logical 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*<br>Bitwise or`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 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 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 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. |
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