日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

利用JEXL实现动态表达式编译

發布時間:2023/12/3 编程问答 33 豆豆
生活随笔 收集整理的這篇文章主要介紹了 利用JEXL实现动态表达式编译 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

轉載自? ?利用JEXL實現動態表達式編譯

背景

做項目突然遇到這樣的需求:
系統要獲取多個數據源的數據,并進行處理,最后輸出多個字段。字段的計算規則一般是簡單的取值最多加一點條件判斷。
而且需要動態變動!!例如一個字段a的取值,如果a > 10的時候輸出10,a <= 10則輸出a。這里的10可能在一天后改成8,也可能在后天就改成了12。當然,如果只是一個數字的變動還好說,我們可以使用數據庫進行存儲。但是,萬一哪天需求突然變成了a < 10的時候輸出10,a >=10 則輸出a,就需要對代碼改動,再測試再發布才能到生產環境使用。
一兩個這樣的字段還沒什么,如果整個系統所依賴的字段都有這樣的屬性,那么我們就需要找一種方法來實現動態的加載邏輯。
下面介紹的JEXL就可以解決這種問題

JEXL(Java Expression Language)介紹

JEXL – Apache Commons JEXL Overview
下面用一些實例來介紹JEXL的使用方法

實例

maven依賴:

<dependency><groupId>org.apache.commons</groupId><artifactId>commons-jexl</artifactId><version>2.0</version> </dependency>

正則表達式匹配

首先寫一個公共方法:

public class Util {public static boolean regMatch(String regEx, String str) {Pattern pattern = Pattern.compile(regEx);return pattern.matcher(str).matches();} }

下面是使用JEXL調用的方法

public void RL() {JexlContext jc = new MapContext();String str = "一二三四五六七八九十";jc.set("Util", new Util());jc.set("str", str);jc.set("ans", "");String expression = "ans = Util.regMatch(\"[\u4e00-\u9fa5]{10,}\",str)";Expression e = new JexlEngine().createExpression(expression);e.evaluate(jc);System.out.println(jc.get("ans")); }

代碼中的expression變量就是可以動態編譯的表達式,這里要注意表達式中出現的所有變量,都需要事先set進JexlContext中,否則會報錯。這里有多種形式的錯誤:
①如果沒有set”Util”,程序運行中會拋出異常。

org.apache.commons.jexl2.JexlException: TmpTest.RL@40![13,40]: 'ans = QeUtil.regMatch('[一-龥]{10,}', str);' attempting to call method on null

②如果沒有set”str”,程序不會拋出異常,并輸出null。如果你的regMatch方法中有判空處理,就會輸出判空的結果。如果沒有判空處理,在控制臺的輸出如下:

警告: TmpTest.RL@39![36,39]: 'ans = QeUtil.regMatch('[一-龥]{10,}', str);' undefined variable str 二月 21, 2017 4:00:41 下午 org.apache.commons.jexl2.JexlEngine invocationFailed 警告: TmpTest.RL@39![13,40]: 'ans = QeUtil.regMatch('[一-龥]{10,}', str);' method invocation error java.lang.NullPointerException

③如果沒有set”ans”,程序會正常運行,并輸出正確值
為了保險起見,建議表達式中出現的所有變量,都需要事先set進JexlContext中

循環

JEXL支持兩種循環方式:

for(item : list) {x = x + item; }

while (x lt 10) {x = x + 2; }

下面是使用while的實例:

public void loop() {JexlContext jc = new MapContext();jc.set("a", 1);jc.set("b", "0");jc.set("ans", new StringBuffer());Expression e = new JexlEngine().createExpression("while (a < 10) {a = a + 1;ans.append(b);}");e.evaluate(jc);System.out.println(jc.get("ans")); }

get\set方法調用

JEXL支持傳入對象,并調用對象的方法
下面的簡單的get\set方法的實例:

public void getSet() {TmpTest tmpTest = new TmpTest();tmpTest.setA(1);JexlContext jc = new MapContext();jc.set("tmpTest", tmpTest);jc.set("ans", "");Expression e = new JexlEngine().createExpression("ans = tmpTest.getA()");e.evaluate(jc);System.out.println(jc.get("ans"));e = new JexlEngine().createExpression("ans = tmpTest.setA(2)");e.evaluate(jc);TmpTest tmpTest1 = (TmpTest) jc.get("tmpTest");System.out.println(tmpTest1.getA()); }

上面的用例會在控制臺先輸出1,再輸出2

總結

以上是生活随笔為你收集整理的利用JEXL实现动态表达式编译的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。