|
Common Expression Language(CEL)表达式指南 |
|
一. 表达式规则:
(1) 常规中缀表达式规则
(2) 支持Java所有表达式
二. 特殊表达式符号:
1. () 括号:加强优先级
2. " ' ` 引号:字符串表示符,字符串中转义符"\",与Java中使用方式相同 (注:除了双引号,单引号,还加入了反单引号,便于多层嵌套)
3. 数字:以0-9开头表示数字
以0x开头的为16进制数字,如:0xF5A7
以0开头的整数为8进制数字,如:07
后缀B/b, S/s, I/i, L/l, F/f, D/d,分别表示Byte, Short, Integer, Long, Float, Double
无点号缺省为Integer,有点号缺省为Double
4. 关键字:表示特殊值 (注:不可以作为变量名)
null 空值
true, false 布尔值
this 代表当前LocalContext
super 代表上级LocalContext
context 代表当前Context
三. 标准操作符:
(1) 对象(Object):
. 点号, 属性取值, 如: ${user.name}
[ ] 方括号, 索引属性, 如: ${user["name"]} ${user[nameVar]}
一元 & 类或包名前缀, 如: ${&com.xxx.XxxUtils.xxx} ${&XxxUtils.xxx}
instanceof 类型判断,如:${user1 instanceof "com.xxx.User"}
== 值相等比较,名称符eq, 如: ${user1 == user2} ${user1 eq user2}(注:相近类型如char与string,int与long等对比时,会自动转换类型)
!= 值不相等比较,名称符ne, 如: ${user1 != user2} ${user1 ne user2}
(2) 布尔值(Boolean):
&& 逻辑与,名称符and, 如: ${user1.agree && user2.agree} ${user1.agree and user2.agree}
|| 逻辑或,名称符or, 如: ${user1.agree || user2.agree} ${user1.agree or user2.agree} $for{user : (users1 || users2 || users3} (注:对非Boolean值对象,将返回非null对象,与JavaScript规则相同)
^ 逻辑异或,名称符xor, 如: ${user1.agree ^ user2.agree} ${user1.agree xor user2.agree}
! 逻辑非, 如: ${! user1.agree}
?: 逻辑选择, 如: ${user1.agree ? "yes" : "no"}
(3) 数字(Number):
+ 正数,如:${3 * +2} ${+user1.coins}
- 负数, 如: ${3 * -2} ${-user1.coins}
+ 加法运算, 如: ${user1.coins + 3.2D}
- 减法运算, 如: ${user1.coins - user2.coins}
* 乘法运算, 如: ${user.coins * 2}
/ 除法运算, 如: ${user.coins / 2}
% 求模运算, 如: ${user.coins % 2}
** 求幂次方运算, 如: ${2 ** 2 ** 3}
| 按位与运算,如: ${128 | 256}
& 按位或运算,如: ${128 & 2}
^ 按位异或运算,如: ${~128 ^ 2}
~ 按位取反运算,如: ${~128}
>> 按位右移运算,如: ${32 >> 2}
<< 按位左移运算,如: ${128 << 2}
>>> 按位无符号右移运算,如: ${32 >>> 2}
> 数字大于比较,名称符gt, 如: ${user1.coins > user2.coins} ${user1.coins gt user2.coins}
< 数字小于比较,名称符lt, 如: ${user1.coins < user2.coins} ${user1.coins lt user2.coins}
>= 数字大于等于比较,名称符ge, 如: ${user1.coins >= user2.coins} ${user1.coins ge user2.coins}
<= 数字小于等于比较,名称符le, 如: ${user1.coins <= user2.coins} ${user1.coins le user2.coins}
<=> 数字大小全比较,名称符cmp,0表示相等,1表示大于,-1表示小于, 如: ${user1.coins <=> user2.coins} ${user1.coins cmp user2.coins}
~= 数字近似值等于比较, 如: ${user1.coins ~= user2.coins}
# 数字格式化, 如: ${user1.coins # "###,##0.###"}
(4) 字符串(String):
+ 两个字符串相连, 非字符将调用其toString, 如: ${user.firstname + user.lastname}
* 字符串重复, 如: ${"aaa" * 3} ${3 * "aaa"}
- 将String倒序, 如: ${-str}
@ 输出不转义地址串, 如: ${@"C:\native\user\file.txt"}
> 字符串大于比较, 如: $if{user1.name > user2.name}
< 字符串小于比较, 如: $if{user1.name < user2.name}
>= 字符串大于等于比较, 如: $if{user1.name >= user2.name}
<= 字符串小于等于比较, 如: $if{user1.name <= user2.name}
<=> 字符串大小全比较,0表示相等,1表示大于,-1表示小于, 如: ${user1.name <=> user2.name}
~= 字符串忽略大小写比较,并且忽略两端空格, 如: ${"aa" ~= "AA"} $if{user1.name ~= user2.name}
^= 字符串是否以另一字符串开头,也就是startsWith, 如: ${"abcd" ^= "ab"} $if{user1.name ^= "james"}
$= 字符串是否以另一字符串结尾,也就是endsWith, 如: ${"abcd" $= "cd"} $if{user1.name $= "lee"}
*= 字符串是否包含另一字符串,也就是containsWith, 如: ${"abcd" *= "bc"} $if{user1.name *= "lee"}
~ 字符串正则表达式匹配, 如: $if{code ~ "^[0-9]+$"}
!~ 字符串正则表达式不匹配, 如: $if{code !~ "^[0-9]+$"}
(5) 日期(Date):
+ 日期年数后推, 如: ${user.registerDate + 3.year} (注:参见数字属性扩展)
- 日期年数前推, 如: ${user.registerDate - 3.year}
> 日期大于比较, 如: ${user1.registerDate > user2.registerDate}
< 日期小于比较, 如: ${user1.registerDate < user2.registerDate}
>= 日期大于等于比较, 如: ${user1.registerDate >= user2.registerDate}
<= 日期小于等于比较, 如: ${user1.registerDate <= user2.registerDate}
<=> 日期大小全比较,0表示相等,1表示大于,-1表示小于, 如: ${user1.registerDate <=> user2.registerDate}
~= 日期忽略时分秒比较, 如: ${user1.registerDate ~= user2.registerDate}
# 日期格式化, 如: ${user.registerDate # "yyyy-MM-dd"}
(6) 集合(Collection):
[ ] 方括号, 数组或List下标,如: ${list[1]} ${list[1..3]} ${list[1,2,4]} ${string[1..3]}
注:${String[0..2]}会将String看成char[ ]使用,数组或List下标为负数时表示倒数:${list[-1]},取list的倒数第一个元素
[ ] 方括号, Map索引, 如: ${map["key"]} ${map[keyVar]},同样可以用${map.key},但点号优先查getter属性,方括优先查entry键值对,如:${map.size}和${map["size"]},如果map中有size的entry,则返回结果可能不一样。
[prop=value] 属性索引,List如:${users[name="james"].coins}将从列表中返回第一个属性"name"值为"james"的user对象,也可以是多个属性${users[name="james",role="admin"]},Map如:${map[value="james"].key}通过value查key,${map[key="james"].value}与${map["james"]}等价
=> 筛选过滤器,隐含状态信息index,size,count,index为当前项索引号,size为集合大小,count为已接收数,List缺省变量名为item,如:${list[=> item ~ "[0-9]+" && count < 3]} ${users[u => u.name != 'guest']},Map缺省变量名为entry,如:${map[=> entry.key != 'xxx' && count < 3]} ${map[x => x.key != 'xxx']}
.. 双点号, 表示序列(Sequence), 如: ${1..5} $for{seq : 1..5} $for{weekDay : "Sunday".."Saturday"}
, 逗号, 表示列表(List), 如: ${1,2,5,7} $for{seq : (1,2,5,7)}
: 冒号, 表示键值对(Entry), 如: ${user.nameVar : "james"} ${name : "james"}
注:entry采用JSON的设计风格,因为key通常是字符串,而非变量,所以当key为无引号名称时,将会作为字符串处理,而不是变量取值,如果要用变量作为key,在key前加反斜杠: ${\name : "james"},另请注意:${user.name : "james"}会取user.name变量的值作为key, 因为点号先运算.
:, 冒号加逗号, 表示哈希表(Map), 如: ${a : 1, b: 2, c : 7} $for{rel : (a : 1, b: 2, c : 7)}
[ ] 一元方括号, 转换成集合, 将Object转成List, 将Entry转成Map, 如: $for{num : [100]} $for{num : [name:value]}
注:如果[ ]中已经是List或Map, 则将保持不变, 相当于( ), 如: $for{num : [20,50,100]} $for{num : [name1:value1, name2:value2]}
+ 加号,两个List或Map相连, 如: ${items + ("a","b")}
- 一元减号,将List或Array倒序, 如: ${-items}
~ 判断集合内是否有匹配项,如:$if{state ~ (1, 2, 4)} $if{user1 ~ users}
!~ 判断集合内是否没有匹配项,如:$if{state !~ (1, 2, 4)} $if{user1 !~ users}
orderby 按属性排序,+号升序(可省),-号降序, 如: $for{book : books orderby ("-price","+title","author")}
(7) 系统(System):
. 一元点号,取系统属性,如:${.now} $if{user.timeLimit >= .now} ${.random} ${.uuid} ${.system.currentTimeMillis} ${.system.properties["user.dir"]} ${.engine.versionNumber} ${.engine.releaseDate} ${.engine.vendor}
七. 操作符结合律及优先级
结合律:(注:可以用括号改变结合)
优先级高的先结合,
一元操作符之间总是从右到左结合,
同优先级的二元操作符从左到右结合。
优先级:(注:括号的优先级总是最高)
操作符优先级从低到高依次为:
一元:"=>"
"="
","
":"
"?:"
"~", "!~"
"#"
"|", "&", ">>", "<<", ">>>"
"^" "||"
"&&"
"==" "!=" "~="
"<=" ">=" "<" ">"
".."
"+" "-"
"*" "/" "%"
"**"
一元:"+", "-", "!", "~", "?"
".", "[ ]"
一元:".", "[ ]", "\"
四. 属性扩展
(注:无参数有返回值函数可以直接作为属性,如:trim, toString, size等,下面不再列出)
(1) 空值(Null):
toString 转为String类型,如:null.toString 返回"null"字符串
null的其它任意属性都返回null,如:null.xxx 返回null
任意对象的null属性都返回null,如:obj.null 返回null
null的null属性也返回null,如:null.null 返回null
(2) 对象(Object/Bean):
toJson 输出JSON格式的字符串表示,如:${user.toJson}, ${map.toJson}
toXml 输出XML格式的字符串表示,如:${user.toXml}, ${map.toXml}
(3) 字符串(String):
capital 首字母大写, eg: ${"james".capital} (输出:James)
toDate 以yyyy-MM-dd格式转换为Date, 如: $if{now > "2007-01-01".toDate}
toTime 以HH:mm:ss格式转换为Date, 如: ${"22:10:15".toTime}
toDateTime 以yyyy-MM-dd HH:mm:ss格式转换为Date, 如: $if{now > "2007-01-01 23:10:05".toDateTime}
toCharacter 转为Character类型, 如: ${"a".toCharacter}
toByte 转为Byte类型, 如: ${"1".toByte + 2}
toShort 转为Short类型, 如: ${"1".toShort + 2}
toInteger 转为Integer类型, 如: ${"1".toInteger + 2}
toLong 转为Long类型, 如: ${"25".toLong + 2}
toFloat 转为Float类型, 如: ${"1.2".toFloat + 2}
toDouble 转为Double类型, 如: ${"2.3".toDouble + 2}
md5Code MD5摘要密文, 如: ${"mypassword".md5Code}
shaCode SHA摘要密文, 如: ${"mypassword".shaCode}
base64Code BASE64编码, 如: ${"mail".base64Code}
escapeHtml HTML转码, 将<和>分别转成<和>等, 如: ${"<b>".escapeHtml}
escapeXml XML转码, 如: ${"<book><book>".escapeXml}
escapeUrl URL转码, 如: ${"http://xxx.com?xx=xx&yy=yy".escapeUrl}
escapeJs JS转码, 如: ${"\"\n\"".escapeJs}
(4) 日期(Date):
year, month, day, hour, minute, second, millisecond 时间各个部分取值, 如: ${createDate.day} ${createDate.hour}
week 星期几, 如: ${createDate.week}
dayOfYear 一年中的第多少天, 如: ${createDate.dayOfYear}
weekOfYear 一年中的第几周, 如: ${createDate.weekOfYear}
weekOfMonth 一月中的第几周, 如: ${createDate.weekOfMonth}
era 纪元, 如: ${createDate.era}
century 世纪, 如: ${createDate.century}
timezone 时间参照的时区, 如: ${createDate.timezone}
leap 是否为润年, 如: $if{now.leap}
toDateString 以yyyy-MM-dd格式化日期, 如: ${createDate.toDateString}
toTimeString 以HH:mm:ss格式化日期, 如: ${createDate.toTimeString}
toDateTimeString 以yyyy-MM-dd HH:mm:ss格式化日期, 如: ${createDate.toDateTimeString}
toLong 计算机时间, 即相对于1970-01-01 00:00:00.000的毫秒数, 如: ${createDate.toLong}
(5) 数字(Number):
toDate 以相对于1970-01-01 00:00:00.000的毫秒数转换为Date, 如: ${9999999.toDate}
toSize 根据大小显示Bytes,KB,MB等单位, 如: ${917.toSize}(输出:917Bytes) ${(11 * 1024).toSize}(输出:11KB)
year, month, week, day, hour, minute, second, millisecond,分别表示转换为年,月,周,日,时,分,秒,毫秒等数字单位,如:${createDate + 3.day}
toByte, toShort, toInteger, toLong, toFloat, toDouble 类型间转换, 如: ${3L.toFloat}
(6) 布尔值(Boolean):
not 取反, 如: ${true.not} ${user.allow.not}
(7) 数组(Array):
size 数组长度,保持与List统一,如:${arr.size}
五. 序列扩展
(1) 数字: ${1 .. 20} ${20 .. -12}
(2) 字母: ${'a' .. 'z'} ${'z' .. 'a'} ${'A' .. 'Z'} ${'b' .. 'k'}
(3) 季度: ${"Spring" .. "Winter"}
(4) 月份: ${"January" .. "December"}
(5) 星期: ${"Sunday" .. "Saturday"}
|
|