Aviator表達(dá)式快速上手

遇到的問(wèn)題

最近項(xiàng)目中有這樣一種場(chǎng)景:需要改變部分訂單的結(jié)算方式,這個(gè)改動(dòng)點(diǎn)對(duì)交易結(jié)算影響很大壹置,需要逐步切流以減少風(fēng)險(xiǎn)竞思。訂單有buyerId(買家id)、sellerId(賣家id)钞护、tkBizTag(訂單打標(biāo))……幾十個(gè)字段盖喷,如果case by case硬編碼來(lái)限定切流的場(chǎng)景來(lái)做,就很不靈活难咕,單純這個(gè)切流就要上多次線课梳。
因此有這樣的技術(shù)需求:使用一種靈活多變的切流方式,即可支持對(duì)按照訂單對(duì)象任何一個(gè)參數(shù)滿足某種條件時(shí)進(jìn)行切流步藕,如按照訂單類型字段惦界、某些買家id符合要求。

解決方案

經(jīng)過(guò)調(diào)研咙冗,最終采用aviator表達(dá)式+動(dòng)態(tài)內(nèi)容推送中間件(diamond)來(lái)實(shí)現(xiàn)沾歪。
一個(gè)簡(jiǎn)單的demo如下:

NCpsPaymentDTO paymentDTO = newNCpsPaymentDTO();
paymentDTO.setTkBizTag(5);
paymentDTO.setTbBuyerId(1234L);
ExtraInfo extraInfo = new ExtraInfo();
extraInfo.setEventId(1234567L);
HashMap paramMap= new HashMap();
paramMap.put("paymentDTO",paymentDTO);
paramMap.put("extraInfo",extraInfo);
String configInfo ="paymentDTO.tkBizTag == 5 && paymentDTO.tbBuyerId % 10000 <=2000 && extraInfo.eventId == 1234567";
Expression expression =AviatorEvaluator.compile(configInfo);
Boolean rst = (Boolean)expression.execute(paramMap);
System.out.println(rst);//true

Note:
其中configInfo取自動(dòng)態(tài)內(nèi)容推送中間件diamond,可以根據(jù)需求隨時(shí)更新并推送到各臺(tái)線上機(jī)器雾消。

了解到這個(gè)程度足夠了么灾搏?No.關(guān)于aviator還需要知道得更多。

Aviator簡(jiǎn)介

Aviator是一個(gè)高性能立润、輕量級(jí)的java語(yǔ)言實(shí)現(xiàn)的表達(dá)式求值引擎狂窑,主要用于各種表達(dá)式的動(dòng)態(tài)求值。現(xiàn)在已經(jīng)有很多開(kāi)源可用的java表達(dá)式求值引擎桑腮,為什么還需要Avaitor呢泉哈?
Aviator的設(shè)計(jì)目標(biāo)是輕量級(jí)和高性能,相比于Groovy、JRuby的笨重丛晦,Aviator非常小奕纫,加上依賴包也才450K,不算依賴包的話只有70K;當(dāng)然烫沙,Aviator的語(yǔ)法是受限的匹层,它不是一門完整的語(yǔ)言,而只是語(yǔ)言的一小部分集合锌蓄。
其次升筏,Aviator的實(shí)現(xiàn)思路與其他輕量級(jí)的求值器很不相同,其他求值器一般都是通過(guò)解釋的方式運(yùn)行瘸爽,而Aviator則是直接將表達(dá)式編譯成Java字節(jié)碼您访,交給JVM去執(zhí)行。簡(jiǎn)單來(lái)說(shuō)蝶糯,Aviator的定位是介于Groovy這樣的重量級(jí)腳本語(yǔ)言和IKExpression這樣的輕量級(jí)表達(dá)式引擎之間洋只。

Aviator的特性

  • 支持大部分運(yùn)算操作符辆沦,包括算術(shù)操作符昼捍、關(guān)系運(yùn)算符、邏輯操作符肢扯、正則匹配操作符(=~)妒茬、三元表達(dá)式?:,并且支持操作符的優(yōu)先級(jí)和括號(hào)強(qiáng)制優(yōu)先級(jí)蔚晨,具體請(qǐng)看后面的操作符列表乍钻。
  • 支持函數(shù)調(diào)用和自定義函數(shù)
  • 支持正則表達(dá)式匹配,類似Ruby铭腕、Perl的匹配語(yǔ)法银择,并且支持類Ruby的$digit指向匹配分組。
  • 自動(dòng)類型轉(zhuǎn)換累舷,當(dāng)執(zhí)行操作的時(shí)候浩考,會(huì)自動(dòng)判斷操作數(shù)類型并做相應(yīng)轉(zhuǎn)換,無(wú)法轉(zhuǎn)換即拋異常被盈。
  • 支持傳入變量析孽,支持類似a.b.c的嵌套變量訪問(wèn)。
  • 性能優(yōu)秀

Aviator的限制

  • 沒(méi)有if else只怎、do while等語(yǔ)句袜瞬,沒(méi)有賦值語(yǔ)句,沒(méi)有位運(yùn)算符
  • 僅支持邏輯表達(dá)式身堡、算術(shù)表達(dá)式邓尤、三元表達(dá)式和正則匹配

Aviator用法

最新jar包

    <dependency>
        <groupId>com.googlecode.aviator</groupId>
        <artifactId>aviator</artifactId>
        <version>2.3.4</version>
    </dependency>

算術(shù)表達(dá)式

Long result = (Long)AviatorEvaluator.execute("1+2+3");
System.out.println(result);//6

note:Aviator的數(shù)值類型僅支持Long和Double,任何整數(shù)都將轉(zhuǎn)換成Long,任何浮點(diǎn)數(shù)都將轉(zhuǎn)換為Double,包括用戶傳入的變量數(shù)值。

邏輯表達(dá)式

Boolean result2 = (Boolean)AviatorEvaluator.execute("3>1 && 2!=4 || true");
System.out.println(result2);//true

變量和字符串相加

Map env = newHashMap();
env.put("yourname","aviator");
String result3 = (String)AviatorEvaluator.execute(" 'hello ' + yourname ", env);
System.out.println(result3);

上面的例子演示了怎么向表達(dá)式傳入變量值,表達(dá)式中的yourname是一個(gè)變量汞扎,默認(rèn)為null殿漠,通過(guò)傳入Map的變量綁定環(huán)境,將yourname設(shè)置為你輸入的名稱佩捞。env的key是變量名绞幌,value是變量的值。
Aviator 2.2開(kāi)始新增加一個(gè)exec方法,可以更方便地傳入變量并執(zhí)行,而不需要構(gòu)造env這個(gè)map了:

String result4= (String) AviatorEvaluator.exec(" 'hello ' + yourname ","aviator2");
System.out.println(result4);

三元表達(dá)式

String result5=(String)AviatorEvaluator.execute("3>0? 'yes':'no'");
System.out.println(result5);

函數(shù)調(diào)用

AviatorEvaluator.execute("string.length('hello')");    //求字符串長(zhǎng)度
AviatorEvaluator.execute("string.contains('hello','h')");  //判斷字符串是否包含字符串AviatorEvaluator.execute("string.startsWith('hello','h')");  //是否以子串開(kāi)頭AviatorEvaluator.execute("string.endsWith('hello','llo')");是否以子串結(jié)尾
AviatorEvaluator.execute("math.pow(-3,2)");   //求n次方
AviatorEvaluator.execute("math.sqrt(14.0)");   //開(kāi) 平方根
AviatorEvaluator.execute("math.sin(20)");    //正弦函數(shù)

參考文章

Aviator官方文檔
Aviator——讓表達(dá)式飛起來(lái)
表達(dá)式引擎aviator

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末一忱,一起剝皮案震驚了整個(gè)濱河市莲蜘,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌帘营,老刑警劉巖票渠,帶你破解...
    沈念sama閱讀 218,036評(píng)論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異芬迄,居然都是意外死亡问顷,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,046評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門禀梳,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)杜窄,“玉大人,你說(shuō)我怎么就攤上這事算途∪” “怎么了?”我有些...
    開(kāi)封第一講書人閱讀 164,411評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵嘴瓤,是天一觀的道長(zhǎng)扫外。 經(jīng)常有香客問(wèn)我,道長(zhǎng)廓脆,這世上最難降的妖魔是什么筛谚? 我笑而不...
    開(kāi)封第一講書人閱讀 58,622評(píng)論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮停忿,結(jié)果婚禮上驾讲,老公的妹妹穿的比我還像新娘。我一直安慰自己瞎嬉,他們只是感情好蝎毡,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,661評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著氧枣,像睡著了一般沐兵。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上便监,一...
    開(kāi)封第一講書人閱讀 51,521評(píng)論 1 304
  • 那天扎谎,我揣著相機(jī)與錄音碳想,去河邊找鬼。 笑死毁靶,一個(gè)胖子當(dāng)著我的面吹牛胧奔,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播预吆,決...
    沈念sama閱讀 40,288評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼龙填,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了拐叉?” 一聲冷哼從身側(cè)響起岩遗,我...
    開(kāi)封第一講書人閱讀 39,200評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎凤瘦,沒(méi)想到半個(gè)月后宿礁,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,644評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡蔬芥,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,837評(píng)論 3 336
  • 正文 我和宋清朗相戀三年梆靖,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片笔诵。...
    茶點(diǎn)故事閱讀 39,953評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡返吻,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出嗤放,到底是詐尸還是另有隱情思喊,我是刑警寧澤壁酬,帶...
    沈念sama閱讀 35,673評(píng)論 5 346
  • 正文 年R本政府宣布次酌,位于F島的核電站,受9級(jí)特大地震影響舆乔,放射性物質(zhì)發(fā)生泄漏岳服。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,281評(píng)論 3 329
  • 文/蒙蒙 一希俩、第九天 我趴在偏房一處隱蔽的房頂上張望吊宋。 院中可真熱鬧,春花似錦颜武、人聲如沸璃搜。這莊子的主人今日做“春日...
    開(kāi)封第一講書人閱讀 31,889評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)这吻。三九已至,卻和暖如春篙议,著一層夾襖步出監(jiān)牢的瞬間唾糯,已是汗流浹背怠硼。 一陣腳步聲響...
    開(kāi)封第一講書人閱讀 33,011評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留移怯,地道東北人香璃。 一個(gè)月前我還...
    沈念sama閱讀 48,119評(píng)論 3 370
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像舟误,于是被迫代替她去往敵國(guó)和親葡秒。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,901評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容

  • Spring Cloud為開(kāi)發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見(jiàn)模式的工具(例如配置管理嵌溢,服務(wù)發(fā)現(xiàn)同云,斷路器,智...
    卡卡羅2017閱讀 134,657評(píng)論 18 139
  • 第5章 引用類型(返回首頁(yè)) 本章內(nèi)容 使用對(duì)象 創(chuàng)建并操作數(shù)組 理解基本的JavaScript類型 使用基本類型...
    大學(xué)一百閱讀 3,233評(píng)論 0 4
  • 第一部分Common Lisp介紹第1章 介紹一下Lisp你在學(xué)的時(shí)候覺(jué)得已經(jīng)明白了堵腹,寫的時(shí)候更加確信了解了炸站,教別...
    geoeee閱讀 2,946評(píng)論 5 8
  • 應(yīng)用方式 1、內(nèi)聯(lián)式 2疚顷、嵌入式 3旱易、外部鏈接式 4、導(dǎo)入式 @import 選擇符類型 1腿堤、類型選擇符 ...
    遙星夢(mèng)閱讀 256評(píng)論 0 0
  • 我們都長(zhǎng)大了 離開(kāi)年少輕狂 離開(kāi)溫暖港灣 我們都長(zhǎng)大了 眼中滿含堅(jiān)定 心中充滿期待 我們褪去稚嫩 我們收獲酸甜...
    三杯茶王一閱讀 379評(píng)論 4 2