<acronym id="s8ci2"><small id="s8ci2"></small></acronym>
<rt id="s8ci2"></rt><rt id="s8ci2"><optgroup id="s8ci2"></optgroup></rt>
<acronym id="s8ci2"></acronym>
<acronym id="s8ci2"><center id="s8ci2"></center></acronym>
0
  • 聊天消息
  • 系統消息
  • 評論與回復
登錄后你可以
  • 下載海量資料
  • 學習在線課程
  • 觀看技術視頻
  • 寫文章/發帖/加入社區
創作中心

完善資料讓更多小伙伴認識你,還能領取20積分哦,立即完善>

3天內不再提示

一文詳解Java表達式引擎選型

OSC開源社區 ? 來源:OSC開源社區 ? 2023-12-06 10:57 ? 次閱讀

一、簡介

我們項目組主要負責面向企業客戶的業務系統,企業的需求往往是多樣化且復雜的,對接不同企業時會有不同的定制化的業務模型和流程。我們在業務系統中使用表達式引擎,集中配置管理業務規則,并實現實時決策和計算,可以提高系統的靈活性和響應能力,從而更好地滿足業務的需求。 舉個簡單的例子,假設我們有一個業務場景,在返利系統中,當推廣員滿足一定的獎勵條件時,就會給其對應的獎勵金額。例如某個產品的具體獎勵規則如下:

f193635e-9362-11ee-939d-92fbcf53809c.png

這個規則看起來很好實現,只要在代碼里寫幾個if else分支就可以了。但是如果返利系統對接了多家供應商,且每家提供的產品的獎勵規則都不同呢?再通過硬編碼的方式寫if else似乎就不太好了,每次增加修改刪除規則都需要系統發版上線。 引入規則引擎似乎就能解決這個問題,規則引擎的一個好處就是可以使業務規則和業務代碼分離,從而降低維護難度,同時它還可以滿足業務人員通過編寫DSL或通過界面指定規則的訴求,這樣就可以在沒有開發人員參與的情況下建立規則了,這種說法聽起來似乎很有道理,但在實踐中卻很少行得通。

首先,規則引擎有一定的學習成本,即使開發人員使用也需要進行專門的學習,更何況沒有任何編程背景的業務人員,其次,其實現的復雜度也高,如果業務規則復雜,規則制定者對規則引擎內部隱藏的程序流程不了解,很可能會得到意想不到的結果,最后,有些規則引擎還存在性能瓶頸。如果對規則引擎和表達式引擎都不熟悉,抽離的業務規則又需要由開發人員來制定,那么相比之下表達式引擎就要容易上手得多,其語法更接近Java,而且有些表達式引擎還會將表達式編譯成字節碼,在執行速度和資源利用方面可能就更有優勢。所以,對于此類業務場景,使用表達式引擎似乎更加合適一些。 本文主要對Java表達式引擎進行概要性介紹和分析,并提供一定建議,為團隊研發過程中對表達式引擎的技術選型提供輸入。

二、技術棧簡介

本文將針對AviatorScript、MVEL、OGNL、SpEL、QLExpress、JEXL、JUEL幾種常見表達式引擎進行選型調研。先簡單介紹一下這幾種表達式引擎。

2.1 AviatorScript

AviatorScript 是一門高性能、輕量級寄宿于 JVM 之上的腳本語言。AviatorScript 可將表達式編譯成字節碼。它原來的定位一直只是一個表達式引擎,不支持 if/else 條件語句,也不支持for/while循環語句等,隨著5.0的發布變身為一個通用腳本語言,支持了這些語言特性。

2.2 MVEL (MVFLEX Expression Language)

MVEL是一種混合的動態/靜態類型的、可嵌入Java平臺的表達式語言,MVEL被眾多Java項目使用。MVEL 在很大程度上受到 Java 語法的啟發,但也有一些本質區別,目的是使其作為一種表達式語言更加高效,例如直接支持集合、數組和字符串匹配的操作符,以及正則表達式。最早版本發布于2007年。 文檔:http://mvel.documentnode.com/?

2.3 OGNL (Object-Graph Navigation Language)

OGNL 是 Object-Graph Navigation Language(對象圖導航語言)的縮寫;它是一種表達式語言,用于獲取和設置 Java 對象的屬性,以及其他額外功能,如列表投影和選擇以及 lambda 表達式。于2005年發布2.1.4版。

2.4 SpEL (Spring Expression Language)

SpEL是一種功能強大的表達式語言,支持在運行時查詢和操作對象圖。該語言的語法與 Unified EL 相似,但提供了更多的功能,其中最主要的是方法調用和基本的字符串模板功能。

2.5 QLExpress

由阿里的電商業務規則、表達式(布爾組合)、特殊數學公式計算(高精度)、語法分析、腳本二次定制等強需求而設計的一門動態腳本引擎解析工具,于2012年開源。

2.6 JEXL (Java Expression Language)

JEXL 旨在促進在 Java 編寫的應用程序和框架中實現動態腳本功能。JEXL 基于對 JSTL 表達式語言的一些擴展實現了一種表達式語言,支持 shell 腳本或 ECMAScript 中的大部分構想。1.0版發布于2005年。

2.7 JUEL (Java Unified Expression Language)

JUEL 是統一表達式語言 (EL) 的實現,該語言是 JSP 2.1 標準 (JSR-245) 的一部分,已在 JEE5 中引入。此外,JUEL 2.2 實現了 JSP 2.2 維護版本規范,完全符合 JEE6 標準。于2006年發布2.1.0版本,2.2.7發布于2014年。

2.8 Janino

Janino是一個超小、超快的Java編譯器,也可以用作表達式引擎,它的性能非常出色,根據官網介紹,Apache Spark、Apache Flink、Groovy等優秀的開源項目都在用Janino。

由于Janino實際是一個Java編譯器,理論上其性能應該更接近于直接執行Java代碼,其次作為表達式引擎使用起來比較復雜。因此,下面的對比中,Janino不參與比較,可以將其作為一個參照。

2.9 其他

如下一些表達式引擎雖然也常見于各技術博客,但由于長期沒有更新維護,因此沒有納入此次選型比較 Fel Fel是輕量級的高效的表達式計算引擎。Fel源自于企業項目,設計目標是為了滿足不斷變化的功能需求和性能需求。項目托管于Google Code,上次更新是2012年,已經十幾年沒有更新了,所以沒有納入此次選型。 ik-expression IK Expression是一個開源的(OpenSource),可擴展的(Extensible),基于java語言開發的一個超輕量級(Super lightweight)的公式化語言解析執行工具包。2009年2月發布第一個版本,2009年10月發布最后一個版本后再沒有新版本發布,所以沒有納入此次選型。 JSEL JSEL是一個兼容 JavaScript 運算規則的簡單的表達式解釋引擎,你可以通過Map接口,或者JavaBean給出一個變量集合,能后通過表達式從這個集合中抽取變量,再通過表達式邏輯生成你需要的數據。2009年發布第一個版本,2011年發布最后一個版本后未再更新,所以沒有納入此次選型。 此外規則引擎如 Drools, urule, easy-rules 不參與此次選型比較。相對比較成熟完善的腳本語言如Groovy也不參與選型比較。這篇文章主要針對相對輕量簡單的表達式引擎進行選型。

三、技術棧選型評估

選擇表達式引擎,我們希望其社區支持情況良好、實現復雜度適中、執行速度快、安全并且簡單易學。所以,接下來將從社區支持情況、引入的大小和依賴、性能、安全性、使用案例和語法幾個方面對幾種表達式引擎進行比較評估。

3.1 社區支持情況

社區支持情況可以輔助評估項目的健康度,有問題是不是能及時解決,項目是不是能持續演進等等,下面列出了GitHub star,watch,fork,last commit等數據,可以作為參考,由于數據隨著時間推移會產生變化,以下僅針對2023.10.29的數據進行分析。

f19700ea-9362-11ee-939d-92fbcf53809c.png

??由于 Spring 項目被廣泛使用,而SpEl又是Spring的一個子項目,所以從各項數據來看SpEl的社區支持情況是最好的。下面先排除SpEl分析其他幾個表達式引擎。 QLExpress,AviatorScript 和 MVEL 在國內使用比較多,這可能是他們star,watch,fork數較高的原因。說明這幾個項目受歡迎度,受認可度,影響力應該較高。 從issues,pull requests數來分析,可以看到 MVEL,AviatorScript 和 QLExpress 高于其他腳本引擎,說明他們的用戶需求和反饋較多,也可能意味著項目面臨較多問題和挑戰。 MVEL,JEXL,OGNL 均有較多貢獻者參與。他們的社區協作、項目可持續性方面應該都比較不錯。 綜合以上分析,除SpEl外,QLExpress,AviatorScript 和 MVEL 的社區支持情況都相對較好。

3.2 引入大小和依賴

代碼大小和依賴可以輔助評估代碼的復雜性,下面列出了各個Github倉庫的代碼大小,可以作為一個參考(實際并不完全準確反映其實現的復雜性)。 以下是2023.10.29的數據

f1a5e588-9362-11ee-939d-92fbcf53809c.png

??JUEL,QLExpress代碼大小最小,都在600多KB;其次是 OGNL 1MB多一點;AviatorScript,MVEL,JEXL 大小都在2MB左右;SpEl由于在 spring-framework 倉庫中,上表中統計的是 spring-framework 的總量,單純看 SpEl 的模塊 spring-expression 的話,大小是1.3MB左右。但是其還依賴了 spring-core 和 spring-jcl,再含這兩個的話,大小 7.4MB左右。 我們再結合各個項目的依賴來分析一下。


+- org.mveljarcompile
+- com.googlecode.aviatorjarcompile
+- com.alibabajarcompile
|  +- commons-beanutilsjarcompile
|  |  - (commons-loggingjarcompile - omitted for conflict with 1.2)
|  - commons-langjarcompile
+- org.codehaus.janinojarcompile
|  - org.codehaus.janinojarcompile
+- ognljarcompile
|  - org.javassistjarcompile
+- org.apache.commonsjarcompile
|  - commons-loggingjarcompile
+- org.springframeworkjarcompile
|  - org.springframeworkjarcompile
|     - org.springframeworkjarcompile
+- de.odysseus.jueljarcompile
+- de.odysseus.jueljarcompile
+- de.odysseus.jueljarcompile
除了SpEl外,QLExpress,OGNL,JEXL也都有其他依賴。 如果考慮 commons-beanutils, commons-lang, commons-logging 三個依賴,QLExpress 引入的大小在 10MB左右。 如果考慮 javassist 依賴,OGNL 引入的大小是4MB多。 如果考慮 commons-logging 依賴,JEXL 引入的大小是2.5MB左右。 綜合來看,JUEL,AviatorScript,MVEL,JEXL 在引入大小和依賴方面要好于其他。

3.3 性能

較好的性能意味著系統能夠快速地響應用戶的請求,減少等待時間,提升體驗。 性能方面主要通過 JMH 在字面量表達式、含有變量的表達式以及含有方法調用的表達式等使用場景對幾個表達式引擎進行測試。 JMH(Java Microbenchmark Harness),是用于代碼微基準測試的工具套件,主要是基于方法層面的基準測試,精度可以達到納秒級。該工具是由 Oracle 內部實現 JIT 的大牛們編寫的,他們應該比任何人都了解 JIT 以及 JVM 對于基準測試的影響。 由于不同表達式引擎語法或特性稍有差別,下面測試中對于差異項會進行說明。

3.3.1 字面量表達式

f1b41bd0-9362-11ee-939d-92fbcf53809c.svg

:1000 + 100.0 * 99 - (600 - 3 * 15) / (((68 - 9) - 3) * 2 - 100) + 10000 % 7 * 71 :6.7 - 100 > 39.6 ? 5 == 5 ? 4 + 5 : 6 - 1 : !(100 % 3 - 39.0 < 27) ? 8 * 2 - 199 : 100 % 3 說明: 由于QlExpress執行第2個表達式時報錯,需要增加圓括號,實際執行的是6.7 - 100 > 39.6 ? (5 == 5 ? 4 + 5 : 6 - 1) : (!(100 % 3 - 39.0 < 27) ? 8 * 2 - 199 : 100 % 3)

結果分析: 可以明顯看到 JEXL,JUEL,QlExpress這三個表達式引擎性能明顯不如其他引擎。 SpEl 在執行第1個算數操作時表現出色,但是在執行第2個嵌套三元操作時明顯不如AviatorScript,MVEL,OGNL引擎。 此輪測試中 AviatorScript,OGNL,MVEL表現出色。AviatorScript,OGNL 執行兩個表達式表現都比較出色,其中AviatorScript略好于OGNL。MVEL 在執行第1個算數操作時表現最出色,但是在執行第2個嵌套三元操作時慢于AviatorScript,OGNL引擎。

3.3.2 含有變量的表達式

f1be1770-9362-11ee-939d-92fbcf53809c.svg

:pi * d + b - (1000 - d * b / pi) / (pi + 99 - i * d) - i * pi * d / b :piDecimal * dDecimal + bDecimal - (1000 - dDecimal * bDecimal / piDecimal) / (piDecimal + 99 - iDecimal * dDecimal) - iDecimal * piDecimal * dDecimal / bDecimal :i * pi + (d * b - 199) / (1 - d * pi) - (2 + 100 - i / pi) % 99 == i * pi + (d * b - 199) / (1 - d * pi) - (2 + 100 - i / pi) % 99 :(clientVersion == '1.9.0' || clientVersion == '1.9.1' || clientVersion == '1.9.2') && deviceType == 'Xiaomi' && weight >= 4 && osVersion == 'Android 9.0' && osType == 'Android' && clientIp != null && requestTime <= now&& customer.grade > 1 && customer.age > 18 說明:

由于不同的表達式引擎在執行第2個表達式時底層實現除法時有所差別,MVEL,AviatorScript,JEXL 執行decimal.divide(otherDecimal, java.math.MathContext.DECIMAL128),其他實際執行的是decimal.divide(otherDecimal, scale, roundingMode),只是參數略有不同,分析時分組進行。

由于QlExpress執行第3個表達式時報錯,不支持非整型mod操作,需要增加類型轉換,實際執行的是i * pi + (d * b - 199) / (1 - d * pi) - (int)(2 + 100 - i / pi) % 99 == i * pi + (d * b - 199) / (1 - d * pi) - (int)(2 + 100 - i / pi) % 99

由于AviatorScript執行第4個表達式時報錯,null的字面量是nil,實際執行的是(clientVersion == '1.9.0' || clientVersion == '1.9.1' || clientVersion == '1.9.2') && deviceType == 'Xiaomi' && weight >= 4 && osVersion == 'Android 9.0' && osType == 'Android' && clientIp != nil && requestTime <= now&& customer.grade > 1 && customer.age > 18

結果分析:

第1個基本類型包裝類的算術計算 SpEl 最優。其次是AviatorScript,MVEL,OGNL。而JEXL,JUEL,QlExpress則不如其他引擎。

第2個BigDecimal類型的算術計算。由于底層實現不同,分為兩組。第1組 MVEL、AviatorScript和JEXL,AviatorScript 優于 MVEL 優于 JEXL。第2組 JUEL,QlExpress,OGNL和SpEl,性能由優到差依次是 OGNL,SpEl,JUEL,QlExpress。并且第1組由于精度更高,性能明顯都差于第2組。

第3個含有基本類型包裝類算數計算的布爾表達式。SpEl 最優,AviatorScript 次之,接下來依次是 OGNL, MVEL,JUEL,JEXL,QlExpress。

第4個含有字符串比較的布爾表達式。AviatorScript,MVEL,JEXL,OGNL 性能優于 JUEL,QlExpress,SpEl。

3.3.3 含有方法調用的表達式

f218a9ec-9362-11ee-939d-92fbcf53809c.svg

:new java.util.Date()

:s.substring(b.d)

:s.substring(b.d).substring(a, b.c.e)

說明:

由于 JUEL 執行new java.util.Date()時報錯,不支持new實例,本輪實際執行的是自定義函數fn:date()

由于 AviatorScript 執行s.substring時報錯,需使用其提供的內部函數,本輪實際執行的是其內部函數string.substring

結果分析:

此輪測試中 SpEl 的表現最優,甚至比Janino還要快。MVEL,AviatorScript次之,在執行構造方法時MVEL要好于AviatorScript。JEXL 表現也比較出色。QlExpress,JUEL,OGNL這三個表達式引擎則不如其他引擎。

3.3.4 總結

綜合以上測試結果,AviatorScript,SpEl,MVEL,OGNL性能表現相對較好。

AviatorScript 性能相對較好,表現均衡,但其語法相較其他引擎跟Java的差異略大。

SpEl 除了在個別場景下性能較差,大部分場景表現非常出色,尤其是在字面量和含有變量的算數計算及方法調用場景下。

MVEL 性能表現相對均衡,含有變量的算術計算略差于AviatorScript,其在字面量算術計算,方法調用場景下表現都非常出色。

OGNL 性能表現也相對均衡,但方法調用場景下表現不佳。

3.4 安全

引入表達式引擎,應該重視系統的安全性和可靠性,比如要防止在不可信環境中被注入惡意腳本,越權執行某些系統命令或使應用停止服務等。安全性方面主要通過漏洞披露、安全指南和配置比較幾種表達式引擎。

3.4.1 漏洞

首先在https://cve.mitre.org/cve/search_cve_list.html通過關鍵字搜索的方式粗略了解一下不同表達式引擎被公開的漏洞。這種方式可能不是非常的準確,由于不同表達式引擎的使用場景、使用方式、關注度的不同可能導致被公開的漏洞存在差異。比如我們所熟悉的 OGNL、SpEl 的關鍵字出現在漏洞中的頻率明顯高于其他表達式引擎。OGNL 在MyBatis和Struts中被使用,SpEl則在Spring中被廣泛使用,這兩個表達式引擎會被大部分項目間接使用,直接將用戶輸入作為表達式的一部分執行,很容易導致出現漏洞。

我們可以從這些公布的漏洞中了解不同表達式引擎可能存在的安全隱患及其修復情況,在使用過程中盡可能避免出現類似問題。

此外,不推薦將表達式執行直接開放到不可信的環境,如果確實需要,應該詳細了解選擇的表達式引擎,是否提供了必要的設置選項可以避免某些安全隱患。

f2358e40-9362-11ee-939d-92fbcf53809c.png

3.4.2 安全設置

AviatorScript,QLExpress,JEXL均從不同程度提供了一些安全選項設置。

AviatorScript

設置白名單


// 在new語句和靜態方法調用中允許使用的類白名單 默認 null 表示無限制
AviatorEvaluator.setOption(Options.ALLOWED_CLASS_SET, Sets.newHashSet(List.class));
// 在new語句和靜態方法調用中允許使用的類白名單 包含子類 默認 null 表示無限制
AviatorEvaluator.setOption(Options.ASSIGNABLE_ALLOWED_CLASS_SET, Sets.newHashSet(List.class));

防止死循環


// 循環最大次數 默認 0 表示無限制
AviatorEvaluator.setOption(Options.MAX_LOOP_COUNT, 10000);

特性開關

// 關閉某些特性
AviatorEvaluator.getInstance().disableFeature(Feature.Module);
AviatorEvaluator.getInstance().disableFeature(Feature.NewInstance);
// 只開啟需要的特性
AviatorEvaluator.setOption(Options.FEATURE_SET, Feature.asSet(Feature.If));

QLExpress

開啟沙箱模式

QLExpressRunStrategy.setSandBoxMode(true);

在沙箱模式中,不可以:

?import Java 類 ?顯式引用 Java 類,比如String a = 'mmm' ?取 Java 類中的字段:a = new Integer(11); a.value ?調用 Java 類中的方法:Math.abs(12)

可以:

?使用 QLExpress 的自定義操作符/宏/函數,以此實現與應用的受控交互

?使用. 操作符獲取 Map 的 key 對應的 value,比如 a 在應用傳入的表達式中是一個 Map,那么可以通過 a.b 獲取

?所有不涉及應用 Java 類的操作

設置白名單


// 設置編譯期白名單
QLExpressRunStrategy.setCompileWhiteCheckerList(Arrays.asList(
    // 精確設置
    CheckerFactory.must(Date.class),
    // 子類設置
    CheckerFactory.assignable(List.class)
));
// 設置運行時白名單// 必須將該選項設置為 true
QLExpressRunStrategy.setForbidInvokeSecurityRiskMethods(true);
// 有白名單設置時, 則黑名單失效
QLExpressRunStrategy.addSecureMethod(RiskBean.class, "secureMethod");

設置黑名單


// 必須將該選項設置為 true
QLExpressRunStrategy.setForbidInvokeSecurityRiskMethods(true);
// 這里不區分靜態方法與成員方法, 寫法一致
// 不支持重載, riskMethod 的所有重載方法都會被禁止
QLExpressRunStrategy.addSecurityRiskMethod(RiskBean.class, "riskMethod");

QLExpess 目前默認添加的黑名單有:

?java.lang.System.exit

?java.lang.Runtime.exec

?java.lang.ProcessBuilder.start

?java.lang.reflect.Method.invoke

?java.lang.reflect.Class.forName

?java.lang.reflect.ClassLoader.loadClass

?java.lang.reflect.ClassLoader.findClass

防止死循環

//可通過timeoutMillis參數設置腳本的運行超時時間:1000ms

Object r = runner.execute(express, context, null, true, false, 1000);

JEXL

使用沙箱


// 使用中應該通過JexlSandbox的重載構造方法進行配置
new JexlBuilder().sandbox(new JexlSandbox()).create();

設置白名單權限

new JexlBuilder().permissions(JexlPermissions.RESTRICTED.compose("com.jd.*")).create();

特性開關


// 關閉循環、new 實例,import等特性
new JexlBuilder().features(new JexlFeatures().loops(false).newInstance(false).importPragma(false)).create();

3.5 使用案例

從業界使用情況可以了解不同表達式引擎的可行性、生態和整合性,以及最佳實踐,進而借鑒。從下表可以看到AviatorScript,MVEL,QLExpress在國內業務線均有使用案例,有些企業也有文章輸出,我們可以借鑒使用。

f239497c-9362-11ee-939d-92fbcf53809c.png

3.6 語法

易于理解和使用的語法可以提高開發效率,并降低學習成本。接下來從類型、操作符、控制語句、集合、方法定義幾方面比較一下不同表達式引擎的語法設計。

類型方面,AviatorScript 設計了特有的類型,使用時需要注意其類型轉換的優先級long->bigint->decimal->double。AviatorScript、MVEL、OGNL、JEXL都支持BigInteger、BigDecimal字面量,這意味著進行精確計算時可以使用字面量,將更方便,如10.24B就表示一個BigDecimal字面量(AviatorScript中BigDecimal字面量后綴是M)。此外AviatorScript、QLExpress還支持高精度計算的設置項。

操作符方面,QLExpress支持替換、自定義操作符及添加操作符別名,這可能有助于簡化復雜表達式或使表達式更加直觀,不過添加預置函數應該可以達到差不多的效果。AviatorScript也支持自定義部分操作符,不過支持數量相當有限。AviatorScript、SpEl、JEXL支持正則匹配操作符。

控制語句方面,除OGNL、SpEl、JUEL不支持控制語句外,其他都支持,不過需要注意 AviatorScript 的 else if 語法有些特殊寫作 elsif,foreach語句跟Java也有所不同。

集合方面,除JUEL外其他都提供了快捷定義的方式,只不過語法不同。

函數定義方面,SpEl、JUEL均不支持,OGNL支持偽lambda定義,其他都支持定義函數。QLExpress不支持定義lambda。

綜合來看,和Java語法都或多或少存在一些差異。AviatorScript設計了自己特有的一些語法,使用的話需要熟悉一下。QLExpress支持自定義操作符,可以使表達式看起來更直觀。MVEL、JEXL的語法可能更接近Java,讓人更容易接受一些。OGNL、SpEl、JUEL的語法更簡單一些,不支持控制語句和函數定義,當然也可以通過預置一些函數變通解決一些較復雜的問題。

四、選型建議

社區方面,SpEl無疑是最活躍的。AviatorScript,QLExpress,MVEL在國內很受歡迎,QLExpress 有阿里背書。

代碼大小和依賴方面,AviatorScript,MVEL 依賴少,并且代碼大小也偏小。

性能方面,如果你使用表達式引擎執行字面量算術計算或方法調用偏多可以選用SpEl,MVEL。如果希望整體性能表現較好可以選用 AviatorScript。

安全方面,如果想自定義安全選項,可以考慮 AviatorScript,QLExpress和JEXL。

使用案例方面,AviatorScript,MVEL,QLExpress在國內都有實際使用案例可循。

語法方面,可能存在一些主觀因素,僅供參考,個人覺得MVEL、JEXL的語法設計使用起來會更容易一些。

通過對以上幾個方面的評估和分析,希望可以幫助團隊基于自身情況及偏好選擇最適合自己項目的Java表達式引擎。

審核編輯:黃飛

聲明:本文內容及配圖由入駐作者撰寫或者入駐合作網站授權轉載。文章觀點僅代表作者本人,不代表電子發燒友網立場。文章及其配圖僅供工程師學習之用,如有內容侵權或者其他違規問題,請聯系本站處理。 舉報投訴
  • JAVA
    +關注

    關注

    19

    文章

    2905

    瀏覽量

    103097

原文標題:Java表達式引擎選型調研分析

文章出處:【微信號:OSC開源社區,微信公眾號:OSC開源社區】歡迎添加關注!文章轉載請注明出處。

收藏 人收藏

    評論

    相關推薦

    輕量級Java表達式引擎aviator的基本使用

    aviator本來是一個輕量級、高性能的基于JVM的表達式引擎。不過從5.0.0版本開始,aviator升級成為了aviatorScript,成為一個高性能、輕量級寄宿于 JVM (包括 Android 平臺)之上的腳本語言。
    發表于 09-13 09:42 ?391次閱讀

    Java Lambda表達式的新特性

    Java Lambda表達式Java 8中最重要的新特性之一。 它們是一種可傳遞的匿名函數,可以作為參數傳遞給方法或存儲在變量中,因此可以在需要的時候調用它們。 基礎 1. 簡介 Lambda
    的頭像 發表于 09-30 10:29 ?2306次閱讀

    shell正則表達式學習

    程序設計語言都支持利用正則表達式進行字符串操作。例如,在Perl中就內建了個功能強大的正則表達式引擎。正則表達式在檢索或替換上遠比之前用到
    發表于 07-25 17:18

    如何創建正則的表達式?

    正則表達式:用于匹配規律規則的表達式,正則表達式最初是科學家對人類神經系統的工作原理的早期研究,現在在編程語言中有廣泛的應用,經常用于表單校驗,高級搜索等。
    發表于 10-27 15:49

    防范表達式的失控

    在C 語言中,表達式是最重要的組成部分之一,幾乎所有的代碼都由表達式構成。表達式的使用如此廣泛,讀者也許會產生這樣的疑問,像+ 、- 、3 、/ 、& & 這樣簡單的運算也會出現
    發表于 04-22 16:57 ?13次下載

    關于java正則表達式的用法詳解

    正則表達式 一個正則表達式是一個用于文本搜索的文本模式。換句話說,在文本中搜索出現的模式。例如,你可以用正則表達式搜索網頁中的郵箱地址或超鏈接。 正則表達式示例 下面是一個簡單的
    發表于 09-27 14:24 ?0次下載

    Python正則表達式指南

    本文介紹了Python對于正則表達式的支持,包括正則表達式基礎以及Python正則表達式標準庫的完整介紹及使用示例。本文的內容不包括如何編寫高效的正則表達式、如何優化正則
    發表于 03-26 09:13 ?10次下載
    Python正則<b class='flag-5'>表達式</b>指南

    Lambda表達式詳解

    C++11中的Lambda表達式用于 **定義并創建匿名的函數對象** ,以簡化編程工作。下面看一下Lambda表達式的基本構成。
    的頭像 發表于 02-09 11:28 ?863次閱讀

    表達式與邏輯門之間的關系

    邏輯表達式是指表示一個表示邏輯運算關系的式子,是一個抽象的類似數學表達式,下面我們重點說明下其表達式與邏輯門之間的關系。
    的頭像 發表于 02-15 14:54 ?1169次閱讀
    <b class='flag-5'>表達式</b>與邏輯門之間的關系

    C語言的表達式

    在C語言中,表達式是由操作符和操作數組成。表達式可以由一個或者多個操作數組成,不同的操作符與操作數組成不同的表達式,因此,表達式才是C語言的基本。
    的頭像 發表于 02-21 15:09 ?981次閱讀
    C語言的<b class='flag-5'>表達式</b>

    邏輯運算符與表達式

    在C語言中,我們通常會進行真值與假值的判斷,這時我們就需要用到邏輯運算符與邏輯表達式。如果表達式的值不為0,則通通返回為真值。只有當表達式的值為0時,才會返回假值。
    的頭像 發表于 02-21 15:16 ?1477次閱讀
    邏輯運算符與<b class='flag-5'>表達式</b>

    一文詳解Verilog表達式

    表達式由操作符和操作數構成,其目的是根據操作符的意義得到一個計算結果。表達式可以在出現數值的任何地方使用。
    的頭像 發表于 05-29 16:23 ?2031次閱讀
    一文<b class='flag-5'>詳解</b>Verilog<b class='flag-5'>表達式</b>

    如何使用lambda表達式提升開發效率?

    Java8 的一個大亮點是引入 Lambda 表達式,使用它設計的代碼會更加簡潔。當開發者在編寫 Lambda 表達式時,也會隨之被編譯成一個函數式接口。
    發表于 08-24 10:25 ?177次閱讀

    zabbix觸發器表達式 基本RS觸發器表達式 rs觸發器的邏輯表達式

    zabbix觸發器表達式 基本RS觸發器表達式 rs觸發器的邏輯表達式? Zabbix是一款開源的監控軟件,它能通過監控指標來實時監測服務器和網絡的運行狀態,同時還能提供警報和報告等功能來幫助管理員
    的頭像 發表于 08-24 15:50 ?1252次閱讀

    怎么去選擇使用gm的三種表達式呢?

    我們在寫跨導gm的表達式時,知道gm有三種表達式。表達式含有的變量其實只有三個,一個W/L,一個Vgs-Vth,還有一個Id。
    的頭像 發表于 09-17 15:31 ?3480次閱讀
    怎么去選擇使用gm的三種<b class='flag-5'>表達式</b>呢?
    亚洲欧美日韩精品久久_久久精品AⅤ无码中文_日本中文字幕有码在线播放_亚洲视频高清不卡在线观看
    <acronym id="s8ci2"><small id="s8ci2"></small></acronym>
    <rt id="s8ci2"></rt><rt id="s8ci2"><optgroup id="s8ci2"></optgroup></rt>
    <acronym id="s8ci2"></acronym>
    <acronym id="s8ci2"><center id="s8ci2"></center></acronym>