這款輕量級 Java 表達(dá)式引擎棠隐,真不錯

  • aviator基本使用

  • 基本表達(dá)式

  • 表達(dá)式變量

  • 使用函數(shù)

  • aviatorScript腳本


aviator本來是一個輕量級酥夭、高性能的基于JVM的表達(dá)式引擎斑举。不過從5.0.0版本開始搅轿,aviator升級成為了aviatorScript,成為一個高性能富玷、輕量級寄宿于 JVM (包括 Android 平臺)之上的腳本語言璧坟。

根據(jù)官網(wǎng)的介紹既穆,aviator支持的主要特性:

  1. 支持?jǐn)?shù)字、字符串雀鹃、正則表達(dá)式幻工、布爾值、正則表達(dá)式等基本類型褐澎,完整支持所有 Java 運(yùn)算符及優(yōu)先級等会钝。
  2. 函數(shù)是一等公民伐蒋,支持閉包和函數(shù)式編程
  3. 內(nèi)置 bigint/decimal類型用于大整數(shù)和高精度運(yùn)算工三,支持運(yùn)算符重載得以讓這些類型使用普通的算術(shù)運(yùn)算符 +-*/參與運(yùn)算。
  4. 完整的腳本語法支持先鱼,包括多行數(shù)據(jù)俭正、條件語句、循環(huán)語句焙畔、詞法作用域和異常處理等。
  5. 函數(shù)式編程結(jié)合 Sequence 抽象宏多,便捷處理任何集合。
  6. 輕量化的模塊系統(tǒng)伸但。
  7. 多種方式,方便地調(diào)用 Java 方法更胖,完整支持 Java 腳本 API(方便從 Java 調(diào)用腳本)。
  8. 豐富的定制選項(xiàng)却妨,可作為安全的語言沙箱和全功能語言使用。
  9. 輕量化彪标,高性能,ASM 模式下通過直接將腳本翻譯成 JVM 字節(jié)碼捞烟,解釋模式可運(yùn)行于 Android 等非標(biāo) Java 平臺薄声。

使用場景包括:

  1. 規(guī)則判斷及規(guī)則引擎
  2. 公式計(jì)算
  3. 動態(tài)腳本控制
  4. 集合數(shù)據(jù) ELT 等

aviator基本使用

基本表達(dá)式

要使用aviator,只需要添加相應(yīng)依賴:

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

然后就可以進(jìn)行表達(dá)式求值了:

    // 返回值為16
    Long r = (Long) AviatorEvaluator.execute("2 * (3 + 5)");

為了提升性能坷襟,往往先編譯表達(dá)式奸柬,然后可以反復(fù)執(zhí)行,進(jìn)行表達(dá)式求值:

    Expression expression = AviatorEvaluator.compile("2 * (3 + 5)");
    Long r = (Long) expression.execute();

aviator支持?jǐn)?shù)字婴程、字符串廓奕、布爾值等基本數(shù)據(jù)類型,數(shù)字類型值都當(dāng)作long或double類型處理。關(guān)注工眾號:碼猿技術(shù)專欄桌粉,回復(fù)關(guān)鍵詞:1111 獲取阿里內(nèi)部java性能調(diào)優(yōu)手冊蒸绩!所以上面例子的求值結(jié)果是Long。

aviator表達(dá)式支持大部分的運(yùn)算操作符铃肯,如常用的算術(shù)運(yùn)算操作符(+患亿、-、*押逼、/步藕、%)、邏輯運(yùn)算操作符(&&挑格、||咙冗、!)漂彤、比較運(yùn)算操作符(>雾消、>=、==挫望、!=立润、<、<=)媳板、位運(yùn)算操作符(&桑腮、|、^拷肌、<<到旦、>>)和優(yōu)先級操作符,還支持三元操作表達(dá)(?:)巨缘、正則表達(dá)式(=~)添忘。

一些例子:

    // 返回 hello world
    String r = (String) AviatorEvaluator.execute("'hello' + ' world'");
    
    // 返回 true
    Boolean r = (Boolean) AviatorEvaluator.execute("100 > 80 && 30 < 40");
    
    // 三元表達(dá)式,返回 30
    Long r = (Long) AviatorEvaluator.execute("100 > 80 ? 30 : 40");
    
    // 正則表達(dá)式若锁,正則表達(dá)式放在//之間搁骑,返回 true
    Boolean r = (Boolean) AviatorEvaluator.execute("'hello' =~ /[\\w]+/");

表達(dá)式變量

跟其他表達(dá)式引擎一樣,aviator也是支持表達(dá)式求值時傳入?yún)?shù)的:

    Long a = 12L;
    Boolean r = (Boolean) AviatorEvaluator.exec("a > 10", a);

參數(shù)也可以是一個列表又固,如下:

    List<Long> a = new ArrayList<>();
    a.add(12L);
    a.add(20L);
    Boolean r = (Boolean) AviatorEvaluator.exec("a[0] > 10", a);

也可以是一個對象:

    public static class Person {
        private String name;
        private Integer age;
    }

    Person a = new Person("movee", 25);
    Boolean r = (Boolean) AviatorEvaluator.exec("a.age > 10", a);

跟一般地仲器,aviator會將參數(shù)放到一個map中

    Map<String, Object> env = new HashMap<>();
    env.put("person", new Person("movee", 25));
    env.put("a", 20L);
    Object result = AviatorEvaluator.execute("person.name", env);

這樣一來,aviator可以非常方便的從json字符串中提取子json字符串

    String jsonStr = """
        {
            "a": {
                "b": [
                        {
                            "x": 3
                        },
                        {
                            "x": 4
                        }
                    ]
            }
        }
        """;


    JSONObject jsonObj = new JSONObject(jsonStr);
    // 結(jié)果返回 3
    Object value = AviatorEvaluator.execute("a.b[0]['x']", jsonObj.toMap());

使用函數(shù)

aviator已經(jīng)提供了很多開箱即用的函數(shù)了:

    // 返回
    Long r = (Long) AviatorEvaluator.execute("math.round(4.3)");
    
    // 返回5
    Long r = (Long) AviatorEvaluator.execute("string.length('hello')");
    
    // 返回一個ArrayList:[1,2,3]
    Object r = AviatorEvaluator.execute("seq.list(1,2,3)");

更詳細(xì)的內(nèi)置函數(shù)列表請參考:aviator函數(shù)庫列表

我們也可以自定義一個java函數(shù)仰冠,自己編寫一個類,繼承aviator的AbstractFunction類洋只,然后實(shí)現(xiàn)相應(yīng)的方法即可:

public class AddFunction extends AbstractFunction {

        /**
         * 函數(shù)實(shí)現(xiàn)的功能
         * @param env 參數(shù)
         * @param arg1 函數(shù)的第一個參數(shù)
         * @param arg2 函數(shù)的第二個參數(shù)
         * @return 返回值
         */
        @Override
        public AviatorObject call(Map<String, Object> env, AviatorObject arg1, AviatorObject arg2) {
            long num1 = FunctionUtils.getNumberValue(arg1, env).longValue();
            long num2 = FunctionUtils.getNumberValue(arg2, env).longValue();
            return AviatorLong.valueOf(num1+num2);
        }

        /**
         * 注冊到aviator的名字
         * @return 函數(shù)名字
         */
        @Override
        public String getName() {
            return "add";
        }
    }

然后就可以注冊到aviator中,像使用內(nèi)置函數(shù)一樣使用自定義函數(shù):

    // 注冊
    AviatorEvaluator.addFunction(new AddFunction());
    
    // 使用
    long sum = (Long) AviatorEvaluator.getInstance().execute("add(3,4)");

aviatorScript腳本

aviator已經(jīng)升級為一個腳本語言妒茬,所以不僅僅能進(jìn)行表達(dá)式求值乍钻,還可以執(zhí)行腳本程序银择。

    // 返回
    Object r = AviatorEvaluator.execute("if (true) { return 1; } else { return 2; }");

aviatorScript腳本一般放到獨(dú)立的腳本文件中谨履,文件名后綴一般為.av

例如,我們編寫一個hello.av腳本文件,內(nèi)容為:

    if (a > 10) {
        return 10;
    } else {
        return a;
    }

然后就可以執(zhí)行該腳本文件害捕,并傳入?yún)?shù)a的值:

    Map<String, Object> env = new HashMap<>();
    env.put("a", 30);
    Expression exp = AviatorEvaluator.getInstance().compileScript("./hello.av", true);
    Object result = exp.execute(env);

官方文檔:https://github.com/killme2008/aviatorscript

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末尝盼,一起剝皮案震驚了整個濱河市盾沫,隨后出現(xiàn)的幾起案子殿漠,更是在濱河造成了極大的恐慌,老刑警劉巖蕾哟,帶你破解...
    沈念sama閱讀 219,188評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件谭确,死亡現(xiàn)場離奇詭異逐哈,居然都是意外死亡问顷,警方通過查閱死者的電腦和手機(jī)薯鼠,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,464評論 3 395
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來哗戈,“玉大人,你說我怎么就攤上這事纱注∧” “怎么了瞎嬉?”我有些...
    開封第一講書人閱讀 165,562評論 0 356
  • 文/不壞的土叔 我叫張陵厚柳,是天一觀的道長别垮。 經(jīng)常有香客問我碳想,道長,這世上最難降的妖魔是什么胧奔? 我笑而不...
    開封第一講書人閱讀 58,893評論 1 295
  • 正文 為了忘掉前任螟左,我火速辦了婚禮胶背,結(jié)果婚禮上喘先,老公的妹妹穿的比我還像新娘。我一直安慰自己红且,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,917評論 6 392
  • 文/花漫 我一把揭開白布嗤放。 她就那樣靜靜地躺著次酌,像睡著了一般岳服。 火紅的嫁衣襯著肌膚如雪希俩。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,708評論 1 305
  • 那天璃搜,我揣著相機(jī)與錄音盒刚,去河邊找鬼因块。 笑死涡上,一個胖子當(dāng)著我的面吹牛拒名,可吹牛的內(nèi)容都是我干的增显。 我是一名探鬼主播同云,決...
    沈念sama閱讀 40,430評論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼星澳!你這毒婦竟也來了禁偎?” 一聲冷哼從身側(cè)響起如暖,我...
    開封第一講書人閱讀 39,342評論 0 276
  • 序言:老撾萬榮一對情侶失蹤盒至,失蹤者是張志新(化名)和其女友劉穎妄迁,沒想到半個月后登淘,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,801評論 1 317
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡耍鬓,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,976評論 3 337
  • 正文 我和宋清朗相戀三年牲蜀,在試婚紗的時候發(fā)現(xiàn)自己被綠了涣达。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片度苔。...
    茶點(diǎn)故事閱讀 40,115評論 1 351
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖浑度,靈堂內(nèi)的尸體忽然破棺而出寇窑,到底是詐尸還是另有隱情,我是刑警寧澤箩张,帶...
    沈念sama閱讀 35,804評論 5 346
  • 正文 年R本政府宣布甩骏,位于F島的核電站,受9級特大地震影響先慷,放射性物質(zhì)發(fā)生泄漏饮笛。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,458評論 3 331
  • 文/蒙蒙 一熟掂、第九天 我趴在偏房一處隱蔽的房頂上張望缎浇。 院中可真熱鬧,春花似錦赴肚、人聲如沸素跺。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,008評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至牡借,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間碴里,已是汗流浹背睡互。 一陣腳步聲響...
    開封第一講書人閱讀 33,135評論 1 272
  • 我被黑心中介騙來泰國打工嗓违, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留疏日,地道東北人涕滋。 一個月前我還...
    沈念sama閱讀 48,365評論 3 373
  • 正文 我出身青樓锨用,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子澄耍,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,055評論 2 355

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