本文將力求用最簡單的語言和實例,介紹一下 OGNL 的語法規則,文章主要內容參考自官方文檔http://commons.apache.org/proper/commons-ognl/language-guide.html
- 本篇主要是語法介紹篇,實戰放在一下篇
- 因為本篇文章將是后 quick-fix 2.0 版本支持 ognl 的前導篇,先提前放出
1. 前言
ognl,全稱 Object Graphic Navigation Language(對象圖導航語言),根據約定的一些簡單的規則,組裝一個利於閱讀、可執行的表達式語句
如下面是一個典型的表達式
"name".toCharArray()[0].numericValue.toString()
即便完全不懂 ognl,單純的以 java 的基礎知識就可以看懂,而這就是 ognl 的魅力所在 (學習一點點東西,就可以馬上入手)
2. 對象定位
說明,這一小節的內容為我個人為了方便理解而分類的,並不官方
我們知道在 java 中,一切都是對象,所以我們的 ognl 表達式必然是着手於某一個對象的,通常在 ognl 中,可以將待執行目標對象划分為三類
- 簡單對象:(如基本數據類型,String)
- 非簡單對象:(非簡單對象,實例訪問)
- 靜態對象:(靜態類)
在 gonl 的語法中,上面三種 case,根據不同的開頭來標記
靜態對象
簡單來說就是我想訪問靜態類的某個方法(或者靜態類的成員)
@java.lang.Math
語法規則為根據@
開始,后面接上完整的類名
一個實例 case 如下,相當於 java 代碼中直接調用Math.max(10, 20)
@java.lang.Math@max(10, 20)
非簡單對象
訪問一個普通對象的成員 or 方法
#demo
語法規則為根據#
開頭,后面為對象名(說明,這個對象需要在 Ognl 的上下文中,且可以根據對象名可以唯一定位)
簡單對象
即基本類型的對象訪問,不加任何前綴,直接使用即可,如下
// 字符串的長度
"name".length()
// 數字計算
1+2
// boolean
true
3. 方法調用
執行目標對象的某個方法,規則如下
// 非基本對象的方法訪問,#開頭,對象與方法之間用.連接
#obj.method( 參數 )
// 靜態對象的方法訪問,@開頭,對象與方法之間用@連接
@xxx@method( 參數 )
// 基本對象的方法訪問,和非基本對象方法方式一致
"name".length()
4. 成員訪問
訪問目標對象的成員,規則如下
// 非基本對象的成員訪問,#開頭,對象與成員之間用.連接
#obj.field
// 靜態對象的成員訪問,@開頭,對象與成員之間用@連接
@xxx@field
// 基本對象的成員訪問,和非基本對象成員方式一致
"name".hash
5. 集合
ognl 針對常用的集合進行了特殊的支持
List
通過{}創建列表,通過[]來訪問對象下標的元素
下面表示創建一個列表,有三個元素: 1,2,3; 獲取列表中下標為 2 的元素
{1, 2, 3}[2]
Arrays
數組,可以結合 new 來使用
new int[] {1,2,3}
Map
{k:v, k:v} 方式來創建 map
下面的語句,表示創建一個 map,並獲取其中 key 為 name 的元素
#{ "name" : "一灰灰Blog", "age" : 18}["name"]
6. 表達式語句
前面是一些簡單的,基本的成員訪問,方法調用,除此之外還存在更牛逼的用法,支持表達式的執行
成員賦值
#demo.name = "一灰灰blog"
表達式計算
500 + 20 - 30 * 3
三目運算符
"name".length() % 2 == 0 ? "偶數長度" : "奇數長度"
集合支持
針對集合做了一些簡化,方便調用
// in 語句,判斷列表中是否包含
"name" in {"name", "hello"}
// 遍歷集合,獲取所有的偶數
{1,2,3,4,5,6}.{? #this % 2 == 0}
// 遍歷集合,獲取第一個滿足條件的元素
{1,2,3,4,5,6}.{^ #this % 2 == 0}
// 遍歷集合,獲取最后一個滿足條件的元素
{1,2,3,4,5,6}.{$ #this % 2 == 0}
對象創建
可以直接通過 new 來創建一個對象,當我們需要執行的目標方法的參數為非基本類型時,可能會非常好用
// new + 完整的類名
new java.lang.String("hello world")
鏈式語句
什么是鏈式語句呢?
有點類似設計模式中的 Builder 模式,我要執行一串的操作,最后獲取目標
定義規則如下,圓括號包裹起來,中間用逗號分隔,依次執行,最后一個為需要返回的目標
(step1, step2,..., result)
結合上面的對象創建,可以實現非常強大的功能
package git.hui;
class User {
public String name;
public Integer age;
}
直接創建一個可用的 User 對象,下面執行完畢之后,直接獲取一個屬性被初始化后的 User 對象
(#user=new git.hui.User(), #user.name="一灰灰Blog", #user.age=18, #user)
lambda 表達式
這個有點高端了,首先是定義 lambda 表達式,然后借助前面的鏈式方式調用,下面是一個階乘的 case
#fact = :[#this<=1? 1 : #this*#fact(#this-1)], #fact(3)
II. 其他
1. 一灰灰 Blog: https://liuyueyi.github.io/hexblog
一灰灰的個人博客,記錄所有學習和工作中的博文,歡迎大家前去逛逛
2. 聲明
盡信書則不如,已上內容,純屬一家之言,因個人能力有限,難免有疏漏和錯誤之處,如發現 bug 或者有更好的建議,歡迎批評指正,不吝感激
- 微博地址: 小灰灰 Blog
- QQ: 一灰灰/3302797840
3. 掃描關注
一灰灰 blog
知識星球