# 13.EL表達式
在 ELCube 中,EL表達式以Spring EL表達式為基礎進行改進,因此SpEL語法是基本語法
Spring EL 官方文檔 (opens new window)
在 ELCube 的配置中,主要分為兩大類的表達式
- SpEL表達式 它將直接返回一個數(shù)據(jù)對象
- SpEL模板 它是一個嚴格的
JSON數(shù)據(jù)格式,程序中會對JSON反序列化為數(shù)據(jù)對象再進行使用
兩大類的表達式有各自適用的場景,我們逐漸通過下面的例子來理解它的特點與區(qū)別
# 基本語法
# 基本數(shù)據(jù)類型
2 //整數(shù)
3.14159265358979323846264338327950288 //小數(shù)
6.0221415E+23 // 科學計數(shù)法
0x7FFFFFFF // 16進制數(shù)字
null // 空值
true //真
false //假
"Hello ELCube" //字符串
{ "Bean", 2, 3.1415926 } //內(nèi)聯(lián)列表 List
{ {'a','b'},{'x','y'} } //內(nèi)聯(lián)列表 List
{
"name":"Bean",
"age":31,
"base": {
"nationality":"中國",
"city":"重慶"
}
} //內(nèi)聯(lián)對象 Maps
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# 變量
變量可以在使用語法#variableName表達引用
#key1 // 返回當前表達式所在環(huán)境里的key值,如卡片中獲取卡片字段名為key1的值
# 關(guān)系運算符
2 == 2 // 返回true
3 > 2 // 返回true
3 >= 2 // 返回true
3 < 2 // 返回false
3 <= 2 // 返回false
2 < -5.0 // 返回false
'black' < 'block' // 返回true
2 eq 2
// 更多等價字母變量
// lt (<), gt (>), le (<=), ge (>=), eq (==),
// ne (!=), div (/), mod (%), not (!)
2
3
4
5
6
7
8
9
10
11
12
# 邏輯運算符
// AND
true and false // 返回false
true and 2>1 // 返回true
// OR
true or false // 返回true
true or 2>1 // 返回true
// NOT
!false // 返回true
!(2>1) // 返回false
// 三元運算符 if-then-else的條件邏輯 的表達
true ? 1 : 0 // 返回1
2 > 1 ? 2 : 1 // 返回2
!(2 > 1) ? 2 : 1 // 返回1
// Elvis操作符 三元運算符語法的縮短語法
#name ?: 'Bean' // 如果name有值,返回name的值,否則返回Bean,可以理解為默認值
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
# 數(shù)學運算符
// 加
1 + 2 // 返回 3
// 減
1 - 2 // 返回 -1
// 乘
1 * 2 // 返回 2
// 除
1 / 2 // 返回 0
3 / 2 // 返回 1
3.0 / 2 // 返回 1.5
3.0 / 0 // 報錯,除數(shù)不能為0
// 模
1 % 2 // 返回1
7 % 4 // 返回3
// 綜合例子
8 / 5 % 2 // 返回 1
1 + 2 - 3 * 8 // 返回 -21
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
# 方法調(diào)用
通過java典型的編程語法實現(xiàn)
"abc".substring(2, 3) // 返回c
"abc".toUpperCase() // 返回ABC
2
# 類型
T操作可以被用來指定安裝一個java.lang.ClassClass (the type). 靜態(tài)方法也可以使用該運算符調(diào)用
T(java.lang.Integer).parseInt("123") // 返回123
T(java.lang.Double).parseDouble("123.3") // 返回123.3
new java.util.Date().getTime()/1000 // 返回當前時間戳的秒數(shù),即ELCube標準日期格式
2
3
# 引用
從表達式使用(@)符號查找系統(tǒng)服務的引用
@nk.now() // 獲取當前時間戳(秒)同new java.util.Date().getTime()/1000
@nk.user() // 獲取當前登陸用戶
@nk.user().id // 獲取當前登陸用戶的ID
@nk.user().realname // 獲取當前登陸用戶的名稱,不是登陸用戶名
@dict.json("systemName") // 從字典中獲取systemName的值
2
3
4
5
# 安全導航運算符
安全導航操作符是用來避免NullPointerException,使用?.來調(diào)用對象的屬性或方法
@nk.user()?.id // 獲取當前登陸用戶的ID,如果用戶沒有登陸,即user()沒有值,則返回null
#baseInfo?.name // 返回變量baseInfo中的name屬性,沒有則返回null
data.base?.name // 返回base卡片中的name字段的值,沒有則返回null
data.base?.name ?: "Bean" // 返回base卡片中的name字段的值,沒有則返回Bean
2
3
4
# 集合選擇
語法.?[selectionExpression]過濾收集并返回一個包含原有元素的子集的新的集合
語法.^[selectionExpression]過濾并返回第一個值
語法.$[selectionExpression]過濾并返回最后一個值
{1,2,3,4,5,6,7,8}.?[#this<3] // 返回數(shù)組 [1,2]
{1,2,3,4,5,6,7,8}.^[#this<3] // 返回 1
{1,2,3,4,5,6,7,8}.$[#this<3] // 返回 2
// 返回數(shù)組 [{"name":"Bean","age":31}]
{{"name":"Bean","age":31},{"name":"Max","age":3}}.?[age>10]
2
3
4
5
6
# 集合投影
語法.![selectionExpression]返回一個包含不同數(shù)據(jù)結(jié)構(gòu)的新集合
// 返回數(shù)組 ["Bean","Max"]
{{"name":"Bean","age":31},{"name":"Max","age":3}}.![name]
// 返回數(shù)組 [31,7]
{{"name":"Bean","age":31},{"name":"Max","age":3}}.![age]
// 返回數(shù)組 [{"name":"Bean"},{"name":"Max"}]
{{"name":"Bean","age":31},{"name":"Max","age":3}}.![{name:name}]
2
3
4
5
6
# 表達式模板
表達式模板允許文字文本與一個或多個解析塊的混合,
在SpEL標準語法中使用#{}作為分隔符,
在ElCube高級語法中使用${}作為分隔符
[#{1},${2},"${3}"] // 返回JSON字符串 [1,2,3]
# 基本示例
# 示例1 表達式
data?.user?.name // 返回結(jié)果 Bean
這是一個典型的SpEL表達式例子,它將返回當前單據(jù)user卡片的name字段的值
# 示例2 模板
["#{data?.user?.name}"] // 返回結(jié)果 ["Bean"]
這個例子返回一個JSON數(shù)組,它將當前單據(jù)user卡片的name字段的值作為數(shù)組的一個元素返回
通過示例2我們會發(fā)現(xiàn),在SpEL模板中,我們需要用#{}這個符號將表達式進行包裹,表達式會被替換為具體的數(shù)值,最終返回一個JSON字符串
# 模板示例
# 示例3 模板 反面教材
在示例2中,我們返回了一個字符串數(shù)組,那么,如果我們希望返回一個數(shù)字數(shù)組該怎么做呢?
WARNING
請注意,下面這個例子是個錯誤的做法,僅作為反面示范
從語法角度講,它是合理的,為了在配置的時候能夠更加嚴謹,我們希望表達式模板是一個嚴格的JSON格式,
例子1,不是一個嚴格的JSON,它的值沒有被雙引號包裹
例子2,它雖然用雙引號包裹了表達式,但是返回結(jié)果中的數(shù)字,變成字符串了, 這顯然也不是我們所需要的。
[#{data?.user?.age}] // 返回結(jié)果 [31]
["#{data?.user?.age}"] // 返回結(jié)果 ["31"]
# 示例4 ELCube的 模板 語法
TIP
在ELCube中,我們可以將#替換為$,來完成例子3中不可能做到的事
${}是對SpEL改進后的語法,它會判斷表達式的返回結(jié)果的數(shù)據(jù)類型,將模板替換為符合JSON的格式
["${data?.user?.age}"] // 返回結(jié)果 [31]
# 示例5 使用模板 返回一個對象數(shù)組
["${data?.user}"] // 返回結(jié)果 [{"name":"Bean","age":31}]
# 示例6 使用模板 返回一個對象
"${data?.user}" // 返回結(jié)果 {"name":"Bean","age":31}
# 示例7 使用模板 返回一個更復雜的結(jié)果
{
"user" : "${data?.user}",
"familyList" : "${data?.family}"
}
// 返回結(jié)果
{
"user" : {
"name" : "Bean",
"age" : 31
},
"familyList" : [
{
"name" : "Tan",
"age" : 55,
"relationship" : "father"
},
{
"name" : "Max",
"age" : 7,
"relationship" : "children"
}
]
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
# 表達式示例
那么,我們不使用模板,而僅使用表達式能否得到同樣的效果呢,當然也可以, 只是表達式直接返回數(shù)據(jù)對象,而非JSON格式的字符串
在表達式中,
# 示例8 使用表達式 返回一個復雜對象
下面這3個示例,執(zhí)行結(jié)果是一致的,我們推薦使用第三個例子的方式,表達更嚴謹
{
"user" : #{data?.user},
"familyList" : #{data?.family}
}
2
3
4
{
"user" : ${data?.user},
"familyList" : ${data?.family}
}
2
3
4
{
"user" : "${data?.user}",
"familyList" : "${data?.family}"
}
2
3
4
# 示例8 使用表達式 返回一個復雜數(shù)組
注意
在使用表達式返回數(shù)組的時候,我們需要使用{},而不是[]了,這是SpEL的標準語法,在配置ELCube的過程中, 這兩個區(qū)別點,是最容易搞混的,我們需要細致對待
下面這3個示例,執(zhí)行結(jié)果是一致的,同樣我們推薦使用第三個例子的方式,表達更嚴謹
{
#{data?.user},
#{data?.user1},
#{data?.user2}
}
2
3
4
5
{
${data?.user},
${data?.user1},
${data?.user2}
}
2
3
4
5
{
"${data?.user}",
"${data?.user1}",
"${data?.user2}"
}
2
3
4
5