自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

太強了!動態(tài)腳本引擎QLExpress,實現(xiàn)各種復(fù)雜的業(yè)務(wù)規(guī)則

開發(fā) 前端
在眾多規(guī)則引擎中,QLExpress以其簡潔的語法、高性能的執(zhí)行能力和靈活的配置選項脫穎而出。它不僅能夠輕松應(yīng)對復(fù)雜的業(yè)務(wù)邏輯,還提供了強大的擴展能力,滿足多樣化的開發(fā)需求。

環(huán)境:Spring2.7.18

1. 簡介

在復(fù)雜的業(yè)務(wù)環(huán)境中,規(guī)則引擎作為系統(tǒng)決策的核心,扮演著非常重要的角色。它們使業(yè)務(wù)邏輯能夠靈活調(diào)整。規(guī)則引擎通過解析和執(zhí)行預(yù)設(shè)的規(guī)則,實現(xiàn)業(yè)務(wù)邏輯的自動化和智能化處理。這不僅提升了系統(tǒng)的靈活性和可擴展性,還大大簡化了業(yè)務(wù)邏輯的維護和管理。基于這樣的需求,尋求一個高效、易用的規(guī)則引擎是非常重要的。

在眾多規(guī)則引擎中,QLExpress以其簡潔的語法、高性能的執(zhí)行能力和靈活的配置選項脫穎而出。它不僅能夠輕松應(yīng)對復(fù)雜的業(yè)務(wù)邏輯,還提供了強大的擴展能力,滿足多樣化的開發(fā)需求。

QLExpress由阿里的電商業(yè)務(wù)規(guī)則、表達式(布爾組合)、特殊數(shù)學公式計算(高精度)、語法分析、腳本二次定制等強需求而設(shè)計的一門動態(tài)腳本引擎解析工具。

QLExpress特性:

  • 線程安全,引擎運算過程中的產(chǎn)生的臨時變量都是threadlocal類型。
  • 高效執(zhí)行,比較耗時的腳本編譯過程可以緩存在本地機器,運行時的臨時變量創(chuàng)建采用了緩沖池的技術(shù),和groovy性能相當。
  • 弱類型腳本語言,和groovy,javascript語法類似,雖然比強類型腳本語言要慢一些,但是使業(yè)務(wù)的靈活度大大增強。
  • 安全控制,可以通過設(shè)置相關(guān)運行參數(shù),預(yù)防死循環(huán)、高危系統(tǒng)api調(diào)用等情況。
  • 代碼精簡,依賴最小,250k的jar包適合所有java的運行環(huán)境。
     

接下來將詳細介紹QLExpress的使用

2. 實戰(zhàn)案例

2.1 引入依賴

<dependency>
  <groupId>com.alibaba</groupId>
  <artifactId>QLExpress</artifactId>
  <version>3.3.3</version>
</dependency>

無需任何配置,可在項目中直接使用了

簡單示例

ExpressRunner runner = new ExpressRunner() ;
DefaultContext<String, Object> context = new DefaultContext<String, Object>() ;
context.put("a", 1) ;
context.put("b", 2) ;
context.put("c", 3) ;
String express = "a + b * c" ;
Object ret = runner.execute(express, context, null, true, false) ;
System.out.printf("%s = %d%n", express, ret) ;

用起來是不是與SpEL表達式差不多?

2.2 語法介紹

基礎(chǔ)語法

支持 +,-,*,/,<,>,<=,>=,==,!=,<>【等同于!=】,%,mod【取模等同于%】,++,--,in【類似sql】,like【sql語法】,&&,||,!,等操作符 

支持for,break、continue、if then else 等標準的程序控制邏輯

示例

ExpressRunner runner = ... ;
DefaultContext<String, Object> context = ... ;
context.put("n", 10) ;
context.put("sum", 0) ;
String express = """
    for(i = 1; i <= n; i++) {
       sum = sum + i;
    }
    return sum;
    """ ;
Object ret = runner.execute(express, context, null, true, false) ;
System.out.printf("表達式: %n%s計算結(jié)果: %d%n", express, ret) ;

輸出結(jié)果

圖片圖片

注意,與java語法相比以下是不支持的:

不支持try{}catch{} 

注釋目前只支持 /** **/,不支持單行注釋 // 

不支持java8的lambda表達式 

不支持for循環(huán)集合操作for (Item item : list) 

弱類型語言,請不要定義類型聲明,更不要用Template(Map<String, List>之類的) 

array的聲明不一樣 

min,max,round,print,println,like,in 都是系統(tǒng)默認函數(shù)的關(guān)鍵字,請不要作為變量名

對象操作

ExpressRunner runner = ... ;
DefaultContext<String, Object> context = ... ;
String express = """
      import com.pack.qlexpress.PersonService ;
      import com.pack.qlexpress.Person ;
      
      ps = new PersonService() ;
      ps.save(new Person()) ;
    """ ;
runner.execute(express, context, null, true, false) ;

輸出結(jié)果

PersonService save method, com.pack.Person@1c3a4799

相當于將java代碼以字符串形式表達出來。注意這里要導(dǎo)入所用到的包,即便在同一包中也要如此操作。

2.3 表達式定義函數(shù)

context.put("arg1", 10) ;
context.put("arg2", 20) ;
String express = """
      function add(int a, int b) {
        return a + b ;
      }
      return Math.PI + add(arg1, arg2) ;
    """ ;
Object ret = runner.execute(express, context, null, true, false) ;
System.out.printf("計算結(jié)果: %s%n", ret) ;

上面表達式中定義了add函數(shù)做加法運算,最終整個表達式調(diào)用add同時再加上Math.PI。對于java.lang包中的類不需要導(dǎo)入操作。

2.4 操作符

String express = """
    if(a > b) {
      return 1;
    } else {
      return 0;
    }
  """ ;
Object ret = runner.execute(express, context, null, true, false) ;
System.out.printf("計算結(jié)果: %s%n", ret) ;

上面表達式做if...else...判斷,輸出結(jié)果:

a <= b
計算結(jié)果: null // 沒有返回結(jié)果,所以為null

對于開發(fā)來說寫上面的表達式太簡單了,如果你非開發(fā)人員來寫if else或者其它更加復(fù)雜的語句那就太難為人了。qlexpress允許我們將這些關(guān)鍵字進行別名的定義,如下示例:

runner.addOperatorWithAlias("如果", "if", null) ;
runner.addOperatorWithAlias("否則", "else", null) ;
runner.addOperatorWithAlias("大于", ">", null) ;
runner.addOperatorWithAlias("返回", "return", null) ;
String express = "如果(a大于b){返回 1;} 否則 {返回 0;}";
Object ret = runner.execute(express, context, null, true, false) ;

上面代碼將程序中的關(guān)鍵字都通過漢字來別名化,這更加適應(yīng)大眾應(yīng)用。

2.5 綁定對象或Method

ExpressRunner runner = new ExpressRunner() ;
runner.addFunctionOfClassMethod("四舍五入", CommonService.class, "roundUp", new Class[] {double.class}, null);
String express = """
      四舍五入(56.54788)
    """ ;
Object ret = runner.execute(express, null, null, true, false) ;
System.out.printf("計算結(jié)果: %s%n", ret) ;

通過addFunctionOfClassMethod方法定義一個對象中的方法。輸出結(jié)果:

計算結(jié)果: 56.55

addFunctionOfClassMethod方法就是對類中的方法進行描述。

2.6 宏定義

ExpressRunner runner = new ExpressRunner() ;
runner.addMacro("計算平均成績", "(語文+數(shù)學+英語) / 3.0");
runner.addMacro("是否優(yōu)秀", "計算平均成績 > 90");
DefaultContext<String, Object> context = new DefaultContext<String, Object>() ;
context.put("語文", 88) ;
context.put("數(shù)學", 99) ;
context.put("英語", 95) ;
Object ret = runner.execute("是否優(yōu)秀", context, null, false, false);
System.out.printf("是否優(yōu)秀: %s%n", ret) ;

輸出結(jié)果

是否優(yōu)秀: true

以上宏的定義可以嵌套的調(diào)用。

2.7 查詢表達式變量

ExpressRunner runner = new ExpressRunner() ;
String express = """
      int ret = (a + b + Math.PI * c ) / 4 ;
      return ret ;
    """ ;
String[] vars = runner.getOutVarNames(express) ;
for (String var : vars) {
  System.out.printf("var: %s%n", var) ;
}

輸出結(jié)果

var: a
var: b
var: c

以上將輸出當前表達式在執(zhí)行時所需要傳入的變量。

責任編輯:武曉燕 來源: Spring全家桶實戰(zhàn)案例源碼
相關(guān)推薦

2025-01-13 13:47:13

2025-02-07 08:16:26

Java開發(fā)者代碼

2025-04-17 02:00:00

2025-01-22 14:02:35

2022-05-30 16:31:08

CSS

2025-02-08 08:00:00

JavaDeepSeekIDEA

2021-03-04 09:31:42

開源技術(shù) 項目

2023-12-10 20:33:50

Redis搜索全文

2024-01-30 09:21:29

CSS文字效果文字裝飾

2021-08-05 16:25:37

Windows 11Windows微軟

2022-06-08 08:01:28

模板字面量類型

2021-09-15 08:45:55

Python文本文件代碼

2023-03-06 08:03:10

Python可視化工具

2020-12-31 11:28:09

GitLabCICD

2021-02-03 20:19:08

Istio流量網(wǎng)格

2022-11-23 22:09:10

Drools規(guī)則引擎

2022-01-26 07:18:57

ES6WeakSetMap

2025-04-02 04:55:00

2024-02-01 12:43:00

模型訓(xùn)練

2025-03-26 08:28:36

點贊
收藏

51CTO技術(shù)棧公眾號