成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

太強了!動態腳本引擎QLExpress,實現各種復雜的業務規則

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

環境:Spring2.7.18

1. 簡介

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

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

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

QLExpress特性:

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

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

2. 實戰案例

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 語法介紹

基礎語法

支持 +,-,*,/,<,>,<=,>=,==,!=,<>【等同于!=】,%,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計算結果: %d%n", express, ret) ;

輸出結果

圖片圖片

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

不支持try{}catch{} 

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

不支持java8的lambda表達式 

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

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

array的聲明不一樣 

min,max,round,print,println,like,in 都是系統默認函數的關鍵字,請不要作為變量名

對象操作

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) ;

輸出結果

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

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

2.3 表達式定義函數

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("計算結果: %s%n", ret) ;

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

2.4 操作符

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

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

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

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

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) ;

上面代碼將程序中的關鍵字都通過漢字來別名化,這更加適應大眾應用。

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("計算結果: %s%n", ret) ;

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

計算結果: 56.55

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

2.6 宏定義

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

輸出結果

是否優秀: true

以上宏的定義可以嵌套的調用。

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) ;
}

輸出結果

var: a
var: b
var: c

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

責任編輯:武曉燕 來源: Spring全家桶實戰案例源碼
相關推薦

2025-01-13 13:47:13

2025-02-07 08:16:26

Java開發者代碼

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

開源技術 項目

2023-12-10 20:33:50

Redis搜索全文

2025-06-09 01:22:00

2024-01-30 09:21:29

CSS文字效果文字裝飾

2022-06-08 08:01:28

模板字面量類型

2021-08-05 16:25:37

Windows 11Windows微軟

2021-02-03 20:19:08

Istio流量網格

2020-12-31 11:28:09

GitLabCICD

2021-09-15 08:45:55

Python文本文件代碼

2023-03-06 08:03:10

Python可視化工具

2022-11-23 22:09:10

Drools規則引擎

2025-05-14 01:00:00

Spring工具工廠類

2022-01-26 07:18:57

ES6WeakSetMap

2025-04-02 04:55:00

點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 日本久久网 | 亚洲一区二区三区久久 | 福利影院在线看 | 精品欧美久久 | 欧美精品一区二区三区在线 | 国产成人网 | 日韩免费av网站 | 国产91精品在线 | 亚洲精品高清视频在线观看 | 久夜精品 | 欧美日韩一 | 亚洲日韩中文字幕一区 | 一区二区免费 | 日韩欧美中文 | 91污在线 | 日韩精品一区二区三区中文在线 | 伊伊综合网 | 日韩精品在线看 | 99久久婷婷国产综合精品首页 | 午夜精品久久 | 久久国产成人午夜av影院武则天 | 天天爱天天操 | 亚洲精品久久久久久一区二区 | 成人不卡在线 | 黄色片视频免费 | 日韩成人免费中文字幕 | 久久久久久久久久一区二区 | 精品国产一二三区 | 狠狠涩 | 国产精品久久久久久久久久 | 久久综合一区二区三区 | 老外黄色一级片 | 伊人激情网 | www.黄色网 | 国产精品自产av一区二区三区 | 先锋资源在线 | 国产中文字幕av | 国产一区 日韩 | 91视频国产一区 | 中文字幕精品一区 | 欧美精品一区二区三区在线播放 |