国产精品嫩草99av在线_一区在线视频观看_欧美高清一区_欧美 日韩 国产 一区_99精品欧美一区二区三区_久久大香伊蕉在人线观看热2_一色屋精品视频在线观看网站_在线亚洲国产精品网站_亚洲区一区二区三区_你懂的视频一区二区

當(dāng)前位置:首頁 > 科技  > 軟件

這款輕量級規(guī)則引擎,真香!

來源: 責(zé)編: 時間:2023-08-09 23:02:29 381觀看
導(dǎo)讀簡介AviatorScript 是一門高性能、輕量級寄宿于 JVM (包括 Android 平臺)之上的腳本語言。它起源于2010年,作者對當(dāng)時已有的一些產(chǎn)品不是很滿意,所以自己擼了一個,它是Groovy的一個定制化的子集。圖片相比較一些傳統(tǒng)的規(guī)則

簡介

AviatorScript 是一門高性能、輕量級寄宿于 JVM (包括 Android 平臺)之上的腳本語言。zBi28資訊網(wǎng)——每日最新資訊28at.com

它起源于2010年,作者對當(dāng)時已有的一些產(chǎn)品不是很滿意,所以自己擼了一個,它是Groovy的一個定制化的子集。zBi28資訊網(wǎng)——每日最新資訊28at.com

圖片圖片zBi28資訊網(wǎng)——每日最新資訊28at.com

相比較一些傳統(tǒng)的規(guī)則引擎,比如Drools、Jess、JRules,它更加輕量級,而且性能更好,同時能力開放,擴(kuò)展很方便。zBi28資訊網(wǎng)——每日最新資訊28at.com

我們來看(吹)看(吹)AviatorScript的特點(diǎn):zBi28資訊網(wǎng)——每日最新資訊28at.com

  1. 它支持?jǐn)?shù)字、字符串、正則表達(dá)式、布爾值等基本類型,并且可以使用所有 Java 運(yùn)算符進(jìn)行運(yùn)算。
  2. 還有一個內(nèi)置的東西叫做 bigint 和 decimal,可以處理超大整數(shù)和高精度運(yùn)算。而且我們還可以通過運(yùn)算符重載讓它們使用普通的算術(shù)運(yùn)算符 +-*/。
  3. 語法非常齊全,可以用它來寫多行數(shù)據(jù)、條件語句、循環(huán)語句,還能處理詞法作用域和異常處理等等。
  4. 如果我們喜歡函數(shù)式編程,還有一個叫做 Sequence 抽象的東西,可以讓你更方便地處理集合。
  5. 還有一個輕量化的模塊系統(tǒng),方便我們組織代碼。
  6. 如果我們需要調(diào)用 Java 方法,也沒問題,可以用多種方式方便地調(diào)用 Java 方法,還有一個完整的腳本 API可以讓你從 Java 調(diào)用腳本。
  7. 性能也是超出想象的好,如果使用 ASM 模式,它會直接將腳本翻譯成 JVM 字節(jié)碼,解釋模式還可以在 Android 等非標(biāo)準(zhǔn) Java 平臺上運(yùn)行。

AviatorScript可以用在各種場景,比如規(guī)則判斷和規(guī)則引擎、公式計(jì)算、動態(tài)腳本控制,甚至集合數(shù)據(jù) ELT 等等。可以說相當(dāng)全能了。zBi28資訊網(wǎng)——每日最新資訊28at.com

快速開始

AviatorScript 是一門寄生在 JVM (Hosted on the JVM)上的語言,類似 clojure/scala/kotlin 等等,我們從寫個Hello World開始。zBi28資訊網(wǎng)——每日最新資訊28at.com

  • 創(chuàng)建一個SpringBoot項(xiàng)目,引入依賴,這里選擇的是最新版本
<dependency>            <groupId>com.googlecode.aviator</groupId>            <artifactId>aviator</artifactId>            <version>5.3.3</version>        </dependency>

PS:可以看到aviator的groupId有一個googlecode,但是它和Google可沒什么關(guān)系,這是因?yàn)樵缙赼viator托管在Google的一個開源項(xiàng)目托管平臺Google Code。zBi28資訊網(wǎng)——每日最新資訊28at.com

  • 在項(xiàng)目的resource目錄下創(chuàng)建一個目錄script,在script目錄下創(chuàng)建腳本hello.av
println("Hello, AviatorScript!");
  • 編寫一個單元測試,運(yùn)行腳本
@Test    void testHello() throws Exception {        //獲取路徑        ClassPathResource resource = new ClassPathResource("script/hello.av");        String scriptPath = resource.getPath();        //編譯        Expression exp = AviatorEvaluator.getInstance().compileScript(scriptPath);        //執(zhí)行        exp.execute();    }

最后執(zhí)行一下,就可以看到輸出:zBi28資訊網(wǎng)——每日最新資訊28at.com

Hello, AviatorScript!
  • 我們也可以直接把腳本定義成字符串,用compile()來進(jìn)行編譯
@Test    void testHelloStr() throws Exception {        //定義腳本        String script="println(/"Hello, AviatorScript!/");";        //編譯        Expression exp = AviatorEvaluator.getInstance().compile(script);        //執(zhí)行        exp.execute();    }

AviatorScript有一個Idea插件,支持直接編譯運(yùn)行Aviator腳本,比較方便。zBi28資訊網(wǎng)——每日最新資訊28at.com

Aviator插件Aviator插件zBi28資訊網(wǎng)——每日最新資訊28at.com


zBi28資訊網(wǎng)——每日最新資訊28at.com

但不足之處,這個插件已經(jīng)不怎么維護(hù)了,只兼容到了Idea2021版本。zBi28資訊網(wǎng)——每日最新資訊28at.com

圖片Idea插件zBi28資訊網(wǎng)——每日最新資訊28at.com

AviatorScript腳本的運(yùn)行,分為兩步,編譯和執(zhí)行。zBi28資訊網(wǎng)——每日最新資訊28at.com

編譯執(zhí)行編譯執(zhí)行zBi28資訊網(wǎng)——每日最新資訊28at.com

編譯支持編譯腳本文件和腳本文本,分別使用compileScript和compile方法。zBi28資訊網(wǎng)——每日最新資訊28at.com

編譯產(chǎn)生的  Expression 對象,最終都是調(diào)用 execute() 方法執(zhí)行。zBi28資訊網(wǎng)——每日最新資訊28at.com

這里有個重要能力,execute 方法可以接受一個變量列表組成的 map,來注入執(zhí)行的上下文:zBi28資訊網(wǎng)——每日最新資訊28at.com

String expression = "a-(b-c) > 100";        Expression compiledExp = AviatorEvaluator.compile(expression);        //上下文        double a=100.3,b=45,c= -199.100;        Map<String, Object> cnotallow=new HashMap<>();        context.put("a",a);        context.put("b",b);        context.put("c",c);        //通過注入的上下文執(zhí)行        Boolean result = (Boolean) compiledExp.execute(context);        System.out.println(result);

我們實(shí)現(xiàn)一些規(guī)則的判斷就是基于這個能力,把一些參數(shù)下上下文傳進(jìn)去,然后進(jìn)行邏輯判斷。zBi28資訊網(wǎng)——每日最新資訊28at.com

基本語法

我們在來看看AviatorScript的基本語法,它的語法相當(dāng)簡潔,比較接近于數(shù)學(xué)表達(dá)式的形式。zBi28資訊網(wǎng)——每日最新資訊28at.com

基本類型及運(yùn)算

AviatorScript 支持常見的類型,如數(shù)字、布爾值、字符串等等,同時將大整數(shù)、BigDecimal、正則表達(dá)式也作為一種基本類型來支持。zBi28資訊網(wǎng)——每日最新資訊28at.com

數(shù)字

AviatorScript 支持?jǐn)?shù)字類型,包括整數(shù)和浮點(diǎn)數(shù),以及高精度計(jì)算(BigDecimal)。數(shù)字類型可以進(jìn)行各種算術(shù)運(yùn)算。zBi28資訊網(wǎng)——每日最新資訊28at.com

整數(shù)和算術(shù)運(yùn)算

整數(shù)類型,對應(yīng)Java中的long類型,可以表示范圍為 -9223372036854774808 ~ 9223372036854774807 的整數(shù)。整數(shù)可以使用十進(jìn)制或十六進(jìn)制表示。zBi28資訊網(wǎng)——每日最新資訊28at.com

let a = 99;let b = 0xFF;let c = -99;println(a + b); // 270println(a / b); // 0println(a - b + c); // -156println(a + b * c); // -9801println(a - (b - c)); // 198println(a / b * b + a % b); // 99

整數(shù)可以進(jìn)行加減乘除和取模運(yùn)算。需要注意的是,整數(shù)相除的結(jié)果仍然是整數(shù),遵循整數(shù)運(yùn)算規(guī)則。可以使用括號來指定運(yùn)算的優(yōu)先級。zBi28資訊網(wǎng)——每日最新資訊28at.com

浮點(diǎn)數(shù)

浮點(diǎn)數(shù)類型對應(yīng)Java中的double類型,表示雙精度 64 位浮點(diǎn)數(shù)。浮點(diǎn)數(shù)可以使用十進(jìn)制或科學(xué)計(jì)數(shù)法表示。zBi28資訊網(wǎng)——每日最新資訊28at.com

let a = 1.34159265;let b = 0.33333;let c = 1e-2;println(a + b); // 1.67492265println(a - b); // 1.00826265println(a * b); // 0.4471865500145println(a / b); // 4.0257402772554println(a + c); // 1.35159265

浮點(diǎn)數(shù)可以進(jìn)行加減乘除運(yùn)算,結(jié)果仍然為浮點(diǎn)數(shù)。zBi28資訊網(wǎng)——每日最新資訊28at.com

高精度計(jì)算(Decimal)

高精度計(jì)算使用 BigDecimal 類型,可以進(jìn)行精確的數(shù)值計(jì)算,適用于貨幣運(yùn)算或者物理公式運(yùn)算的場景。可以通過在數(shù)字后面添加 "M" 后綴來表示 BigDecimal 類型。zBi28資訊網(wǎng)——每日最新資訊28at.com

let a = 1.34M;let b = 0.333M;let c = 2e-3M;println(a + b); // 1.673Mprintln(a - b); // 1.007Mprintln(a * b); // 0.44622Mprintln(a / b); // 4.022022022Mprintln(a + c); // 1.342M

BigDecimal 類型可以進(jìn)行加減乘除運(yùn)算,結(jié)果仍然為 BigDecimal 類型。默認(rèn)的運(yùn)算精度是 MathContext.DECIMAL128,可以通過修改引擎配置項(xiàng) Options.MATH_CONTEXT 來改變。zBi28資訊網(wǎng)——每日最新資訊28at.com

數(shù)字類型轉(zhuǎn)換

數(shù)字類型在運(yùn)算時會自動進(jìn)行類型轉(zhuǎn)換:zBi28資訊網(wǎng)——每日最新資訊28at.com

  • 單一類型參與的運(yùn)算,結(jié)果仍然為該類型。
  • 多種類型參與的運(yùn)算,按照 long -> bigint -> decimal -> double 的順序自動提升,結(jié)果為提升后的類型。

可以使用 long(x) 函數(shù)將數(shù)字強(qiáng)制轉(zhuǎn)換為 long 類型,使用 double(x) 函數(shù)將數(shù)字強(qiáng)制轉(zhuǎn)換為 double 類型。zBi28資訊網(wǎng)——每日最新資訊28at.com

let a = 1;let b = 2;println("a/b is " + a/b); // 0println("a/double(b) is " + a/double(b)); // 0.5

a 和 b 都是 long 類型,它們相除的結(jié)果仍然是整數(shù)。使用 double(b) 將 b 轉(zhuǎn)換為 double 類型后,相除的結(jié)果為浮點(diǎn)數(shù)。zBi28資訊網(wǎng)——每日最新資訊28at.com

字符串

字符串類型由單引號或雙引號括起來的連續(xù)字符組成。可以使用 println 函數(shù)來打印字符串。zBi28資訊網(wǎng)——每日最新資訊28at.com

let a = "hello world";println(a); // hello world

字符串的長度可以通過 string.length 函數(shù)獲取。zBi28資訊網(wǎng)——每日最新資訊28at.com

let a = "hello world";println(string.length(a)); // 11

字符串可以通過 + 運(yùn)算符進(jìn)行拼接。zBi28資訊網(wǎng)——每日最新資訊28at.com

let a = "hello world";let b = "AviatorScript";println(a + ", " + b + "!" + 5); // hello world, AviatorScript!5

字符串還包括其他函數(shù),如截取字符串 substring,都在 string 這個 namespace 下,具體見函數(shù)庫列表。zBi28資訊網(wǎng)——每日最新資訊28at.com

布爾類型和邏輯運(yùn)算

布爾類型用于表示真和假,它只有兩個值 true 和 false 分別表示真值和假值。zBi28資訊網(wǎng)——每日最新資訊28at.com

比較運(yùn)算如大于、小于可以產(chǎn)生布爾值:zBi28資訊網(wǎng)——每日最新資訊28at.com

println("3 > 1 is " + (3 > 1));  // 3 > 1 is trueprintln("3 >= 1 is " + (3 >= 1));  // 3 >= 1 is trueprintln("3 >= 3 is " + (3 >= 3));  // 3 >= 3 is trueprintln("3 < 1 is " + (3 < 1));  // 3 < 1 is falseprintln("3 <= 1 is " + (3 <= 1));  // 3 <= 1 is falseprintln("3 <= 3 is " + (3 <= 3));  // 3 <= 3 is trueprintln("3 == 1 is " + (3 == 1));  // 3 == 1 is falseprintln("3 != 1 is " + (3 != 1));  // 3 != 1 is true

上面演示了所有的邏輯運(yùn)算符:zBi28資訊網(wǎng)——每日最新資訊28at.com

  • > 大于
  • >= 大于等于
  • < 小于
  • <= 小于等于
  • == 等于
  • != 不等于

基本語法

AviatorScript也支持條件語句和循環(huán)語句。zBi28資訊網(wǎng)——每日最新資訊28at.com

條件語句

AviatorScript 中的條件語句和其他語言沒有太大區(qū)別:zBi28資訊網(wǎng)——每日最新資訊28at.com

  • if
if(true) {   println("in if body");}
  • if-else
if(false){   println("in if body");} else {   println("in else body");}
  • if-elsif-else
let a = rand(1100);if(a > 1000) {  println("a is greater than 1000.");} elsif (a > 100) {  println("a is greater than 100.");} elsif (a > 10) {   println("a is greater than 10.");} else {   println("a is less than 10 ");}

循環(huán)語句

AviatorScript提供了兩種循環(huán)語句:for和while。zBi28資訊網(wǎng)——每日最新資訊28at.com

for循環(huán):遍歷集合

for ... in 語句通常用于遍歷一個集合,例如下面是遍歷 0 到 9 的數(shù)字zBi28資訊網(wǎng)——每日最新資訊28at.com

for i in range(0, 10) {  println(i);}

在這里,range(start, end) 函數(shù)用于創(chuàng)建一個整數(shù)集合,包括起始值 start,但不包括結(jié)束值 end。在循環(huán)迭代過程中,變量 i 綁定到集合中的每個元素,并執(zhí)行大括號 {...} 中的代碼塊。zBi28資訊網(wǎng)——每日最新資訊28at.com

range 函數(shù)還可以接受第三個參數(shù),表示遞增的步長大小(默認(rèn)步長為 1)。例如,我們可以打印出0到9之間的偶數(shù):zBi28資訊網(wǎng)——每日最新資訊28at.com

for i in range(0, 10, 2) {  println(i);}

for .. in 可以用于任何集合結(jié)構(gòu),比如數(shù)組、 java.util.List 、 java.util.Map 等等。zBi28資訊網(wǎng)——每日最新資訊28at.com

while循環(huán)

while 循環(huán)本質(zhì)上是將條件語句與循環(huán)結(jié)合在一起。當(dāng)條件為真時,不斷執(zhí)行一段代碼塊,直到條件變?yōu)榧佟?span style="display:none">zBi28資訊網(wǎng)——每日最新資訊28at.com

例如,下面的示例中,變量 sum 從 1 開始,不斷累加自身,直到超過 1000 才停止,然后進(jìn)行打印輸出:zBi28資訊網(wǎng)——每日最新資訊28at.com

let sum = 1;while sum < 1000 {  sum = sum + sum;}println(sum);

循環(huán)可以用這三個關(guān)鍵字結(jié)束——continue/break/return:zBi28資訊網(wǎng)——每日最新資訊28at.com

  • continue用于跳過當(dāng)前迭代,繼續(xù)下一次迭代。
  • break用于跳出整個循環(huán)。
  • return用于中斷整個腳本(或函數(shù))的執(zhí)行并返回。

函數(shù)

我們再來看看AviatorScript一個非常重要的特性——函數(shù)。zBi28資訊網(wǎng)——每日最新資訊28at.com

函數(shù)

函數(shù)定義和調(diào)用

AviatorScript中使用fn語法來定義函數(shù):zBi28資訊網(wǎng)——每日最新資訊28at.com

fn add(x, y) {  return x + y;}three = add(1, 2);println(three);  // 輸出:3s = add('hello', ' world');println(s);  // 輸出:hello world

我們這里通過fn關(guān)鍵字來定義了一個函數(shù),函數(shù)名為add,它接受兩個參數(shù)x和y,并返回它們的和。zBi28資訊網(wǎng)——每日最新資訊28at.com

需要注意的是,AviatorScript是動態(tài)類型系統(tǒng),不需要定義參數(shù)和返回值的類型,它會根據(jù)實(shí)際傳入和返回的值進(jìn)行自動類型轉(zhuǎn)換。因此,我們可以使用字符串來調(diào)用add函數(shù)。zBi28資訊網(wǎng)——每日最新資訊28at.com

函數(shù)的返回值可以通過return語句來指定,也可以省略不寫。在函數(shù)體內(nèi),如果沒有明確的return語句,最后一個表達(dá)式的值將被作為返回值。zBi28資訊網(wǎng)——每日最新資訊28at.com

自定義函數(shù)

再來給大家介紹一個AviatorScript里非常好的特性,支持自定義函數(shù),這給AviatorScript帶來了非常強(qiáng)的擴(kuò)展性。zBi28資訊網(wǎng)——每日最新資訊28at.com

可以通過 java 代碼實(shí)現(xiàn)并往引擎中注入自定義函數(shù),在 AviatorScript 中就可以使用,事實(shí)上所有的內(nèi)置函數(shù)也是通過同樣的方式實(shí)現(xiàn)的:zBi28資訊網(wǎng)——每日最新資訊28at.com

public class TestAviator {    public static void main(String[] args) {        //通通創(chuàng)建一個AviatorEvaluator的實(shí)例        AviatorEvaluatorInstance instance = AviatorEvaluator.getInstance();        //注冊函數(shù)        instance.addFunction(new AddFunction());        //執(zhí)行ab腳本,腳本里調(diào)用自定義函數(shù)        Double result= (Double) instance.execute("add(1, 2)");        //輸出結(jié)果        System.out.println(result);    }}/** * 實(shí)現(xiàn)AbstractFunction接口,就可以自定義函數(shù) */class AddFunction extends AbstractFunction {    /**     * 函數(shù)調(diào)用     * @param env 當(dāng)前執(zhí)行的上下文     * @param arg1 第一個參數(shù)     * @param arg2 第二個參數(shù)     * @return 函數(shù)返回值     */    @Override    public AviatorObject call(Map<String, Object> env,                              AviatorObject arg1, AviatorObject arg2) {        Number left = FunctionUtils.getNumberValue(arg1, env);        Number right = FunctionUtils.getNumberValue(arg2, env);        //將兩個參數(shù)進(jìn)行相加        return new AviatorDouble(left.doubleValue() + right.doubleValue());    }    /**     * 函數(shù)的名稱     * @return 函數(shù)名     */    public String getName() {        return "add";    }}

我們看到:zBi28資訊網(wǎng)——每日最新資訊28at.com

  • 繼承AbstractFunction類,就可以自定義一個函數(shù)
  • 重寫call方法,就可以定義函數(shù)的邏輯,可以通過FunctionUtils獲取腳本傳遞的參數(shù)
  • 通過getName可以設(shè)置函數(shù)的名稱
  • 通過addFunction添加一個自定義函數(shù)類的實(shí)例,就可以注冊函數(shù)
  • 最后就可以在Aviator的腳本里編譯執(zhí)行我們自定義的函數(shù)

好了,關(guān)于AviatorScript的語法我們就不過多介紹了,大家可以直接查看官方文檔[1],可讀性相當(dāng)不錯。zBi28資訊網(wǎng)——每日最新資訊28at.com

接下來我們就來看看AviatorScript的實(shí)際應(yīng)用,看看它到底怎么提升項(xiàng)目的靈活性。zBi28資訊網(wǎng)——每日最新資訊28at.com

實(shí)戰(zhàn)案例

標(biāo)題帶了規(guī)則引擎,在我們的項(xiàng)目里也主要是拿AviatorScript作為規(guī)則引擎使用——我們可以把AviatorScript的腳本維護(hù)在配置中心或者數(shù)據(jù)庫,進(jìn)行動態(tài)地維護(hù),這樣一來,一些規(guī)則的修改,就不用大動干戈地去修改代碼,這樣就更加方便和靈活了。zBi28資訊網(wǎng)——每日最新資訊28at.com

圖片圖片zBi28資訊網(wǎng)——每日最新資訊28at.com

Aviator應(yīng)用zBi28資訊網(wǎng)——每日最新資訊28at.com

客戶端版本控制

在日常的開發(fā)中,我們很多時候可能面臨這樣的情況,兼容客戶端的版本,尤其是Android和iPhone,有些功能是低版本不支持的,或者說有些功能到了高版本就廢棄掉,這時候如果硬編碼去兼容就很麻煩,那么就可以考慮使用規(guī)則腳本的方式。zBi28資訊網(wǎng)——每日最新資訊28at.com

  • 自定義版本比較函數(shù):AviatorScript沒有內(nèi)置版本比較函數(shù),但是可以利用它的自定義函數(shù)特性,自己定義一個版本比較函數(shù)
class VersionFunction extends AbstractFunction {        @Override        public String getName() {            return "compareVersion";        }        @Override        public AviatorObject call(Map<String, Object> env, AviatorObject arg1, AviatorObject arg2) {            // 獲取版本            String version1 = FunctionUtils.getStringValue(arg1, env);            String version2 = FunctionUtils.getStringValue(arg2, env);            int n = version1.length(), m = version2.length();            int i = 0, j = 0;            while (i < n || j < m) {                int x = 0;                for (; i < n && version1.charAt(i) != '.'; ++i) {                    x = x * 10 + version1.charAt(i) - '0';                }                ++i; // 跳過點(diǎn)號                int y = 0;                for (; j < m && version2.charAt(j) != '.'; ++j) {                    y = y * 10 + version2.charAt(j) - '0';                }                ++j; // 跳過點(diǎn)號                if (x != y) {                    return x > y ? new AviatorBigInt(1) : new AviatorBigInt(-1);                }            }            return new AviatorBigInt(0);        }    }
  • 注冊自定義函數(shù):為了方便使用各種自定義函數(shù),我們一般定義一個單例的AviatorEvaluatorInstance,把它注冊成Bean
@Bean    public AviatorEvaluatorInstance aviatorEvaluatorInstance() {        AviatorEvaluatorInstance instance = AviatorEvaluator.getInstance();        // 默認(rèn)開啟緩存        instance.setCachedExpressionByDefault(true);        // 使用LRU緩存,最大值為100個。        instance.useLRUExpressionCache(100);        // 注冊內(nèi)置函數(shù),版本比較函數(shù)。        instance.addFunction(new VersionFunction());    }
  • 在代碼里傳遞上下文:接下來,就可以在業(yè)務(wù)代碼里將一些參數(shù)放進(jìn)執(zhí)行上下文,然然后進(jìn)行編譯執(zhí)行,注意編譯的時候最好要開啟緩存,這樣效率會高很多
/**     *      * @param device 設(shè)備     * @param version 版本     * @param rule 規(guī)則腳本     * @return     */    public boolean filter(String device,String version,String rule){        // 執(zhí)行參數(shù)        Map<String, Object> env = new HashMap<>();        env.put("device", device);        //編譯腳本        Expression expression = aviatorEvaluatorInstance.compile(DigestUtils.md5DigestAsHex(rule.getBytes()), rule, true);        //執(zhí)行腳本        boolean isMatch = (boolean) expression.execute(env);        return isMatch;    }
  • 編寫腳本:接下來就可以編寫和維護(hù)對應(yīng)的規(guī)則腳本,這些規(guī)則腳本通常放在在配置中心或者數(shù)據(jù)庫,方便進(jìn)行動態(tài)變更
if(device==bil){    return false;}## 控制android的版本if (device=="Android" && compareVersion(version,"1.38.1")<0){    return false;}return true;

這樣一來,假如某天,客戶端Bug或者產(chǎn)品原因,需要修改客戶端和客戶端的版本控制,直接修改腳本就好了。zBi28資訊網(wǎng)——每日最新資訊28at.com

甚至我們可以在env里放進(jìn)更多參數(shù),比如uid,可以實(shí)現(xiàn)簡單的黑白名單。zBi28資訊網(wǎng)——每日最新資訊28at.com

我們的自定義函數(shù)除了這種簡單的比較版本,我們還可以放一些復(fù)雜的邏輯,比如判斷是否新用戶等等。zBi28資訊網(wǎng)——每日最新資訊28at.com

營銷活動規(guī)則

假如現(xiàn)在我們的運(yùn)營希望進(jìn)行一場營銷活動,對用戶進(jìn)行一定的支付優(yōu)惠,最開始的一版活動規(guī)則:zBi28資訊網(wǎng)——每日最新資訊28at.com

  • 滿1000減200,滿500減100

這個好寫,一頓if-else就完事了。zBi28資訊網(wǎng)——每日最新資訊28at.com

但是沒過幾天,又改了活動規(guī)則:zBi28資訊網(wǎng)——每日最新資訊28at.com

  • 首單用戶統(tǒng)一減20

好,啪啪改代碼。zBi28資訊網(wǎng)——每日最新資訊28at.com

又過去幾天,活動規(guī)則又改了:zBi28資訊網(wǎng)——每日最新資訊28at.com

  • 隨機(jī)優(yōu)惠不同金額

為了一些多變的營銷規(guī)則,大動干戈,不停修改代碼,耗時費(fèi)力,那么不如用規(guī)則腳本實(shí)現(xiàn):zBi28資訊網(wǎng)——每日最新資訊28at.com

  • 定義腳本
if (amount>=100){    return 200;}elsif(amount>=500){    return 100;}else{    return 0;}
  • 業(yè)務(wù)代碼調(diào)用
public BigDecimal getDiscount(BigDecimal amount,String rule){        // 執(zhí)行規(guī)則并計(jì)算最終價格        Map<String, Object> env = new HashMap<>();        env.put("amount", amount);        Expression expression = aviatorEvaluatorInstance.compile(DigestUtils.md5DigestAsHex(rule.getBytes()), rule, true);        return  (BigDecimal) expression.execute();    }

接下來,再發(fā)生營銷規(guī)則變更,就可以少量開發(fā)(自定義函數(shù),比如判斷首單用戶),并且可以組件化地維護(hù)營銷規(guī)則。zBi28資訊網(wǎng)——每日最新資訊28at.com

訂單風(fēng)控規(guī)則

Aviator我在訂單風(fēng)控里應(yīng)用也很香,風(fēng)控的規(guī)則調(diào)整是相當(dāng)頻繁的,比如一個電商網(wǎng)站,常常要根據(jù)交易的爭議率、交易表現(xiàn)等等,來收緊和放松風(fēng)控規(guī)則,這就要求我們能對一風(fēng)控規(guī)則進(jìn)行快速地配置變更。zBi28資訊網(wǎng)——每日最新資訊28at.com

例如,根據(jù)訂單金額、客戶評級、收貨地址等屬性,自動判斷是否有風(fēng)險并觸發(fā)相應(yīng)的風(fēng)控操作。zBi28資訊網(wǎng)——每日最新資訊28at.com

  • 規(guī)則腳本
if (amount>=1000 || rating <= 2){    return "High";}elsif(amount >= 500 || rating<=4){    return "Mid";}else{    return "Low";}
  • 代碼調(diào)用:這里只是簡單返回了一個風(fēng)控等級,其實(shí)可以通過Map的方式返回多個參數(shù)。
public String riskLevel(BigDecimal amount,String rating,String rule){        // 執(zhí)行規(guī)則并計(jì)算最終價格        Map<String, Object> env = new HashMap<>();        env.put("amount", amount);        env.put("rating", rating);        Expression expression = aviatorEvaluatorInstance.compile(DigestUtils.md5DigestAsHex(rule.getBytes()), rule, true);        return  (String) expression.execute();    }

上面隨手列出了幾個簡單的例子,AviatorScript 還可以用在一些審批流程、事件處理、數(shù)據(jù)質(zhì)量管理等等場景……zBi28資訊網(wǎng)——每日最新資訊28at.com

在一些輕量級的需要規(guī)則引擎的場景下,AviatorScript 真的太香了,尤其是它的擴(kuò)展性,支持通過Java自定義函數(shù),我甚至可以在腳本里查詢數(shù)據(jù)庫、查詢Redis、調(diào)用外部接口……這樣就可以像搭積木一樣搭建想要的功能。zBi28資訊網(wǎng)——每日最新資訊28at.com

總結(jié)

這一期給大家分享了一款輕量級的規(guī)則腳本語言AviatorScript,它的語法豐富,但是很輕量,并且支持非常靈活的擴(kuò)展,在項(xiàng)目中使用可以有效提高業(yè)務(wù)的靈活性,降低開發(fā)的工作量。zBi28資訊網(wǎng)——每日最新資訊28at.com

  1. 本來這期想淺淺盤點(diǎn)一下AviatorScript的設(shè)計(jì)實(shí)現(xiàn),結(jié)果發(fā)現(xiàn)越盤越深,所以就單獨(dú)拆出來,放在下一期了,敬請期待。

本文鏈接:http://www.rrqrq.com/showinfo-26-5131-0.html這款輕量級規(guī)則引擎,真香!

聲明:本網(wǎng)頁內(nèi)容旨在傳播知識,若有侵權(quán)等問題請及時與本網(wǎng)聯(lián)系,我們將在第一時間刪除處理。郵件:2376512515@qq.com

上一篇: 彈性研發(fā)團(tuán)隊(duì)的探索

下一篇: SpringBoot整合WebSocket詳解

標(biāo)簽:
  • 熱門焦點(diǎn)
Top 国产精品嫩草99av在线_一区在线视频观看_欧美高清一区_欧美 日韩 国产 一区_99精品欧美一区二区三区_久久大香伊蕉在人线观看热2_一色屋精品视频在线观看网站_在线亚洲国产精品网站_亚洲区一区二区三区_你懂的视频一区二区
久久精品国产久精国产爱| 日韩一级高清毛片| 亚洲精品社区| 麻豆成人av| 国产精品传媒视频| 99热99精品| 日韩西西人体444www| 91网站在线播放| 亚洲视频在线观看三级| 亚洲国产精品123| 综合自拍亚洲综合图不卡区| 日本久久一区二区三区| 亚洲综合社区| 欧美日韩一级片网站| 天天综合色天天综合色h| 一本色道久久综合亚洲二区三区| 亚洲日本青草视频在线怡红院| 欧美深夜福利| 国产精品久久久久毛片软件| 色综合色综合色综合色综合色综合 | 精品久久国产老人久久综合| 国产成人丝袜美腿| 欧美videos中文字幕| 91在线观看高清| 久久精品日产第一区二区三区高清版| 91玉足脚交白嫩脚丫在线播放| 欧美一区二区三区在线看| 成人av网址在线| 久久久久久久久久电影| 午夜国产精品视频| 中文字幕一区在线观看视频| 亚洲美女91| 亚洲午夜久久久久久久久电影院 | 欧美va亚洲va香蕉在线| 99re热视频这里只精品| 欧美国产在线观看| 99日韩精品| 首页欧美精品中文字幕| 欧美日韩一区二区三区在线| 国产精品亚洲综合一区在线观看| 日韩精品一区二区三区四区视频 | eeuss鲁片一区二区三区| 国产欧美日韩卡一| 亚洲精品少妇| 亚洲第一成年网| 欧美日韩一区二区在线观看| 成人午夜免费电影| 国产精品五月天| 亚洲综合国产| 精品一区二区免费| 精品国产第一区二区三区观看体验 | 国产精品资源网站| 久久久久久影视| 亚洲精品孕妇| 五月婷婷久久丁香| 欧美二区三区的天堂| 99久久精品一区二区| 亚洲女性喷水在线观看一区| 91久久精品国产91性色tv | 亚洲精品中文字幕乱码三区 | 一本一道久久a久久精品综合蜜臀| 国内精品伊人久久久久影院对白| 欧美日韩你懂的| 色综合天天综合网天天看片| 亚洲蜜臀av乱码久久精品 | av成人免费在线观看| 日韩理论在线观看| 色老综合老女人久久久| 成人性生交大片免费看中文| 成人欧美一区二区三区白人| 91久久精品日日躁夜夜躁欧美| 成人av片在线观看| 一区二区三区四区不卡视频 | 欧美日韩精品免费观看视频| 99精品国产99久久久久久白柏 | 国产自产视频一区二区三区| 国产亚洲一本大道中文在线| 免费日韩一区二区| 激情成人午夜视频| 国产欧美一区二区三区鸳鸯浴| 国产一区二区三区免费不卡| 蜜桃视频在线一区| 欧美电影精品一区二区| 亚洲国产免费看| 国内精品伊人久久久久av影院 | 欧美精品黑人性xxxx| 欧美成人一品| 亚洲成人自拍一区| 69av一区二区三区| 国内精品久久久久久久影视蜜臀| 天堂资源在线中文精品| 91精品福利在线一区二区三区 | 日韩成人伦理电影在线观看| 欧美电视剧免费全集观看| 亚洲精品字幕| 久久www免费人成看片高清| 精品久久免费看| 99re66热这里只有精品4| 激情六月婷婷久久| 国产精品乱码一区二三区小蝌蚪| 在线免费亚洲电影| 91免费看`日韩一区二区| 亚洲自拍欧美精品| 精品女同一区二区| 久久精品99| 99久久久国产精品免费蜜臀| 亚洲午夜在线电影| 精品欧美乱码久久久久久1区2区| 宅男噜噜噜66一区二区| 风间由美性色一区二区三区| 亚洲精品一二三| www久久久久| 欧美日韩免费高清| 国产三级久久久| 懂色中文一区二区在线播放| 久久精品盗摄| av影院午夜一区| 午夜免费久久看| 亚洲国产成人自拍| 欧美乱妇一区二区三区不卡视频| 国产亚洲高清视频| a级精品国产片在线观看| 视频一区视频二区在线观看| 国产欧美一区二区三区在线老狼| 欧美亚洲日本国产| 激情欧美一区| 成人一二三区视频| 日韩av成人高清| 亚洲精品大片www| 久久亚洲一区二区三区明星换脸 | 国产精品久久久久一区| 欧美日韩中文另类| 亚洲制服少妇| 欧美极品一区| 高清在线观看日韩| 日日欢夜夜爽一区| 激情久久五月天| 美女被久久久| 爽好多水快深点欧美视频| 国产精品乱码| 午夜视频在线观看一区| 欧洲激情一区二区| 91视视频在线直接观看在线看网页在线看| 中文字幕不卡三区| 亚洲午夜免费福利视频| 亚洲综合视频网| 成人黄色av网站在线| 日本视频一区二区| 亚洲综合小说图片| 中文字幕一区二区三区四区不卡 | 久久综合久久综合久久| 久久久久久穴| 99精品福利视频| 91麻豆国产自产在线观看| 国产麻豆视频精品| 日本欧美一区二区在线观看| 亚洲综合激情网| **欧美大码日韩| 国产精品国产自产拍高清av| 国产亚洲精品资源在线26u| 精品剧情在线观看| 日韩欧美123| 欧美一级精品大片| 日韩一区二区三区四区五区六区| 911精品国产一区二区在线| 欧美羞羞免费网站| 色综合久久久网| 国产精品亚洲产品| 黄色亚洲在线| 91玉足脚交白嫩脚丫在线播放| 国产精品一区二区黑丝| 激情av综合网| 精品影视av免费| 美日韩黄色大片| 天堂成人免费av电影一区| 亚洲成人你懂的| 婷婷激情综合网| 爽爽淫人综合网网站| 日韩成人免费看| 五月天激情综合网| 亚洲电影在线免费观看| 亚洲免费观看视频| 亚洲三级免费电影| 亚洲精品v日韩精品| 中文字幕av在线一区二区三区| 国产欧美日韩在线视频| 国产日韩精品视频一区| 国产欧美精品一区二区色综合 | 国产成人综合亚洲网站| 国产在线麻豆精品观看| 国产毛片精品视频| 国产精品99久久久久久久女警 | 91精品国产全国免费观看| 欧美精品自拍偷拍| 91精彩视频在线| 欧美高清你懂得| 日韩欧美区一区二| 精品国产一区二区亚洲人成毛片| 日韩欧美在线一区二区三区| 日韩欧美一二三区|