Java各種規則引擎

SAPmatinal發表於2019-01-09

更多內容關注公眾號:SAP Technical 

一. Drools規則引擎

  1. 簡介:
Drools就是為了解決業務程式碼和業務規則分離的引擎。
Drools 規則是在 Java 應用程式上執行的,其要執行的步驟順序由程式碼確定
,為了實現這一點,Drools 規則引擎將業務規則轉換成執行樹。
  1. 特性:
優點:
   1、簡化系統架構,優化應用
   2、提高系統的可維護性和維護成本
   3、方便系統的整合
   4、減少編寫“硬程式碼”業務規則的成本和風險

3.原理:

 

Drools.png

  1. 使用方式:

(1)Maven 依賴:

<dependencies>
    <dependency>
        <groupId>org.kie</groupId>
        <artifactId>kie-api</artifactId>
        <version>6.5.0.Final</version>
    </dependency>
    <dependency>
        <groupId>org.drools</groupId>
        <artifactId>drools-compiler</artifactId>
        <version>6.5.0.Final</version>
        <scope>runtime</scope>
    </dependency>
    <dependency>
        <groupId>junit</groupId>
        <artifactId>junit</artifactId>
        <version>4.12</version>
    </dependency>
</dependencies>

(2)新建配置檔案/src/resources/META-INF/kmodule.xml

<?xml version="1.0" encoding="UTF-8"?>
<kmodule xmlns="http://jboss.org/kie/6.0.0/kmodule">
    <kbase name="rules" packages="rules">
        <ksession name="myAgeSession"/>
    </kbase>
</kmodule>

(3)新建drools規則檔案/src/resources/rules/age.drl

import cn.caijiajia.decision.domain.User               // 匯入類

dialect  "mvel"

rule "age"                                      // 規則名,唯一
    when
        $user : User(age<15 || age>60)     //規則的條件部分
    then
        System.out.println("年齡不符合要求!");
end

工程搭建完畢,效果如圖:

專案結構.png

測試用例:

package cn.caijiajia.decision.service;

import cn.caijiajia.decision.domain.User;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.kie.api.KieServices;
import org.kie.api.runtime.KieContainer;
import org.kie.api.runtime.KieSession;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

/**
 * CreateBy: Liurenquan
 * CreateDate: 2018/12/26
 */
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = {"classpath*:applicationContext.xml"})
public class TestUser {

    private static KieContainer container = null;
    private KieSession statefulKieSession = null;

    @Test
    public void test(){
        KieServices kieServices = KieServices.Factory.get();
        container = kieServices.getKieClasspathContainer();
        statefulKieSession = container.newKieSession("myAgeSession");
        User user = new User("duval yang",12);
        statefulKieSession.insert(user);
        statefulKieSession.fireAllRules();
        statefulKieSession.dispose();

    }



}


二.Aviator表示式求值引擎

  1. 簡介:
Aviator是一個高效能、輕量級的java語言實現的表示式求值引擎,主要用於各
種表示式的動態求值。現在已經有很多開源可用的java表示式求值引擎,為什
麼還需要Avaitor呢?

Aviator的設計目標是輕量級和高效能 ,相比於Groovy、JRuby的笨重,Aviator
非常小,加上依賴包也才450K,不算依賴包的話只有70K;當然,Aviator的語法
是受限的,它不是一門完整的語言,而只是語言的一小部分集合。

其次,Aviator的實現思路與其他輕量級的求值器很不相同,其他求值器一般都
是通過解釋的方式執行,而Aviator則是直接將表示式編譯成Java位元組碼,交給
JVM去執行。簡單來說,Aviator的定位是介於Groovy這樣的重量級指令碼語言和
IKExpression這樣的輕量級表示式引擎之間。
  1. 特性:
(1)支援大部分運算操作符,包括算術操作符、關係運算子、邏輯操作符、
正則匹配操作符(=~)、三元表示式?: ,並且支援操作符的優先順序和括號強制優
先級,具體請看後面的操作符列表。
(2)支援函式呼叫和自定義函式。
(3)支援正規表示式匹配,類似Ruby、Perl的匹配語法,並且支援類Ruby的
$digit指向匹配分組。自動型別轉換,當執行操作的時候,會自動判斷運算元類
型並做相應轉換,無法轉換即拋異常。
(4)支援傳入變數,支援類似a.b.c的巢狀變數訪問。
(5)效能優秀。
(6)Aviator的限制,沒有if else、do while等語句,沒有賦值語句,僅支援邏
輯表示式、算術表示式、三元表示式和正則匹配。沒有位運算子

  1. 整體結構:

     

    整體結構.png

  2. maven依賴:

<dependency>
    <groupId>com.googlecode.aviator</groupId>
    <artifactId>aviator</artifactId>
    <version>${aviator.version}</version>
</dependency>
  1. 執行方式
    執行表示式的方法有兩個:execute()、exec();
    execute(),需要傳遞Map格式引數
    exec(),不需要傳遞Map
    示例:
package cn.caijiajia.decision.controller;

import com.googlecode.aviator.AviatorEvaluator;
import java.util.HashMap;
import java.util.Map;

/**
 * CreateBy: Liurenquan
 * CreateDate: 2018/12/25
 */
public class Test {
    public static void main(String[] args) {
        // exec執行方式,無需傳遞Map格式
        String age = "18";
        System.out.println(AviatorEvaluator.exec("'His age is '+ age +'!'", age));



        // execute執行方式,需傳遞Map格式
        Map<String, Object> map = new HashMap<String, Object>();
        map.put("age", "18");
        System.out.println(AviatorEvaluator.execute("'His age is '+ age +'!'", 
map));

    }
}
  1. 使用函式
    Aviator可以使用兩種函式:內建函式、自定義函式
    (1)內建函式

     

    Aviator內建函式.png

Aviator內建函式.png

package cn.caijiajia.decision.service;

import com.googlecode.aviator.AviatorEvaluator;

import java.util.HashMap;
import java.util.Map;

/**
 * CreateBy: Liurenquan
 * CreateDate: 2018/12/25
 */
public class Test {
    public static void main(String[] args) {
        Map<String,Object> map = new HashMap<>();
        map.put("s1","123qwer");
        map.put("s2","123");

  System.out.println(AviatorEvaluator.execute("string.startsWith(s1,s2)",map));

    }
}


(2)自定義函式

自定義函式要繼承AbstractFunction類,重寫目標方法。


package cn.caijiajia.decision.controller;

import com.googlecode.aviator.AviatorEvaluator;
import com.googlecode.aviator.runtime.function.AbstractFunction;
import com.googlecode.aviator.runtime.function.FunctionUtils;
import com.googlecode.aviator.runtime.type.AviatorDouble;
import com.googlecode.aviator.runtime.type.AviatorLong;
import com.googlecode.aviator.runtime.type.AviatorObject;

import java.util.HashMap;
import java.util.Map;

/**
 * CreateBy: Liurenquan
 * CreateDate: 2018/12/25
 */
public class Test {
    public static void main(String[] args) {
        // 註冊自定義函式
        AviatorEvaluator.addFunction(new MultiplyFunction());
        // 方式1
        System.out.println(AviatorEvaluator.execute("multiply(12.23, -2.3)"));
        // 方式2
        Map<String, Object> params = new HashMap<>();
        params.put("a", 12.23);
        params.put("b", -2.3);
        System.out.println(AviatorEvaluator.execute("multiply(a, b)", params));
    }

}

class MultiplyFunction extends AbstractFunction{
    @Override
    public AviatorObject call(Map<String, Object> env, AviatorObject arg1, AviatorObject arg2) {

        double num1 = FunctionUtils.getNumberValue(arg1, env).doubleValue();
        double num2 = FunctionUtils.getNumberValue(arg2, env).doubleValue();
        return new AviatorDouble(num1 * num2);
    }

    @Override
    public String getName() {
        return "multiply";
    }

}
  1. 常用操作符的使用
    (1)操作符列表

     

    操作符列表.png

(2)常量和變數

 

常量和變數.png

(3)編譯表示式

package cn.caijiajia.decision.service;

import com.googlecode.aviator.AviatorEvaluator;
import com.googlecode.aviator.Expression;

import java.util.HashMap;
import java.util.Map;

/**
* CreateBy: Liurenquan
* CreateDate: 2018/12/25
*/
public class Test {
   public static void main(String[] args) {
       String expression = "a+(b-c)>100";
       // 編譯表示式
       Expression compiledExp = AviatorEvaluator.compile(expression);

       Map<String, Object> env = new HashMap<>();
       env.put("a", 100.3);
       env.put("b", 45);
       env.put("c", -199.100);

       // 執行表示式
       Boolean result = (Boolean) compiledExp.execute(env);
       System.out.println(result);

   }
}

(4) 訪問陣列和集合
List和陣列用list[0]和array[0],Map用map.date

package cn.caijiajia.decision.service;

import com.googlecode.aviator.AviatorEvaluator;
import com.googlecode.aviator.Expression;

import java.util.*;

/**
 * CreateBy: Liurenquan
 * CreateDate: 2018/12/25
 */
public class Test {
    public static void main(String[] args) {

        final List<String> list = new ArrayList<>();
        list.add("hello");
        list.add(" world");

        final int[] array = new int[3];
        array[0] = 0;
        array[1] = 1;
        array[2] = 3;

        final Map<String, Date> map = new HashMap<>();
        map.put("date", new Date());

        Map<String, Object> env = new HashMap<>();
        env.put("list", list);
        env.put("array", array);
        env.put("map", map);

        System.out.println(AviatorEvaluator.execute(
                "list[0]+':'+array[0]+':'+'today is '+map.date", env));

    }

}

(5) 三元比較符

package cn.caijiajia.decision.controller;

import com.googlecode.aviator.AviatorEvaluator;

import java.util.HashMap;
import java.util.Map;

/**
 * CreateBy: Liurenquan
 * CreateDate: 2018/12/25
 */
public class Test {
    public static void main(String[] args) {

        Map<String, Object> env = new HashMap<String, Object>();
        env.put("a", -5);
        String result = (String) AviatorEvaluator.execute("a>0? 'yes':'no'", env);
        System.out.println(result);
    }

}

(6) 正規表示式匹配

package cn.caijiajia.decision.controller;

import com.googlecode.aviator.AviatorEvaluator;

import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

/**
 * CreateBy: Liurenquan
 * CreateDate: 2018/12/25
 */
public class Test {
    public static void main(String[] args) {
        String email = "hello2018@gmail.com";
        Map<String, Object> env = new HashMap<String, Object>();
        env.put("email", email);
        String username = (String) AviatorEvaluator.execute("email=~/([\\w0-8]+)@\\w+[\\.\\w+]+/ ? $1 : 'unknow' ", env);
        System.out.println(username);
    }
}

(7) 變數的語法糖衣


package cn.caijiajia.decision.controller;

import com.googlecode.aviator.AviatorEvaluator;

import java.util.HashMap;
import java.util.Map;

/**
 * CreateBy: Liurenquan
 * CreateDate: 2018/12/25
 */
public class Test {
    public static void main(String[] args) {
        User user = new User(1,"jack","18");
        Map<String, Object> env = new HashMap<>();
        env.put("user", user);

        String result = (String) AviatorEvaluator.execute(" '[user id='+ user.id + ',name='+user.name + ',age=' +user.age +']' ", env);
        System.out.println(result);
    }
}



package cn.caijiajia.decision.controller;

/**
 * CreateBy: Liurenquan
 * CreateDate: 2018/12/25
 */
public class User {

    private int id;

    private String name;

    private String age;

    public User() {
    }

    public User(int id, String name, String age) {
        this.id = id;
        this.name = name;
        this.age = age;
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getAge() {
        return age;
    }

    public void setAge(String age) {
        this.age = age;
    }

    @Override
    public String toString() {
        return "User{" +
                "id=" + id +
                ", name='" + name + '\'' +
                ", age='" + age + '\'' +
                '}';
    }

}

(8) nil物件[任何物件都比nil大除了nil本身]

nil是Aviator內建的常量,類似java中的null,表示空的值。nil跟null不同的在
於,在java中null只能使用在==、!=的比較運算子,而nil還可以使用>、>=、
<、<=等比較運算子。Aviator規定,[任何物件都比nil大除了nil本身]。使用者傳入
的變數如果為null,將自動以nil替代。

        AviatorEvaluator.execute("nil == nil");  //true 
        AviatorEvaluator.execute(" 3> nil");    //true 
        AviatorEvaluator.execute(" true!= nil");    //true 
        AviatorEvaluator.execute(" ' '>nil ");  //true 
        AviatorEvaluator.execute(" a==nil ");   //true,a is null
nil與String相加的時候,跟java一樣顯示為null

(9) 日期比較

package cn.caijiajia.decision.controller;

import com.googlecode.aviator.AviatorEvaluator;

import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

/**
 * CreateBy: Liurenquan
 * CreateDate: 2018/12/25
 */
public class Test {
    public static void main(String[] args) {
        Map<String, Object> env = new HashMap<String, Object>();
        final Date date = new Date();
        String dateStr = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss:SS").format(date);
        env.put("date", date);
        env.put("dateStr", dateStr);

        Boolean result = (Boolean) AviatorEvaluator.execute("date==dateStr",
 env);
        System.out.println(result);

        result = (Boolean) AviatorEvaluator.execute("date > '2009-12-20 
00:00:00:00' ", env);
        System.out.println(result);

        result = (Boolean) AviatorEvaluator.execute("date < '2200-12-20 
00:00:00:00' ", env);
        System.out.println(result);

        result = (Boolean) AviatorEvaluator.execute("date ==date ", env);
        System.out.println(result);


    }
}

(10) 語法手冊

資料型別

  • Number型別:數字型別,支援兩種型別,分別對應Java的Long和Double,也就是說任何整數都將被轉換為Long,而任何浮點數都將被轉換為Double,包括使用者傳入的數值也是如此轉換。不支援科學計數法,僅支援十進位制。如-1、100、2.3等。

  • String型別: 字串型別,單引號或者雙引號括起來的文字串,如'hello world',變數如果傳入的是String或者Character也將轉為String型別。

  • Bool型別: 常量true和false,表示真值和假值,與java的Boolean.TRUE和Boolean.False對應。

  • Pattern型別: 類似Ruby、perl的正規表示式,以//括起來的字串,如//d+/,內部實現為java.util.Pattern。

  • 變數型別: 與Java的變數命名規則相同,變數的值由使用者傳入,如"a"、"b"等

  • nil型別: 常量nil,類似java中的null,但是nil比較特殊,nil不僅可以參與==、!=的比較,也可以參與>、>=、<、<=的比較,Aviator規定任何型別都n大於nil除了nil本身,nil==nil返回true。使用者傳入的變數值如果為null,那麼也將作為nil處理,nil列印為null。

算術運算子

Aviator支援常見的算術運算子,包括+ - <tt></tt> / % 五個二元運算子,和一元運算子"-"。其中 - <tt></tt> / %和一元的"-"僅能作用於Number型別。

"+"不僅能用於Number型別,還可以用於String的相加,或者字串與其他物件的相加。Aviator規定,任何型別與String相加,結果為String。

邏輯運算子

Avaitor的支援的邏輯運算子包括,一元否定運算子"!",以及邏輯與的"&&",邏輯或的"||"。邏輯運算子的運算元只能為Boolean。

關係運算子

Aviator支援的關係運算子包括"<" "<=" ">" ">=" 以及"=="和"!=" 。
&&和||都執行短路規則。

關係運算子可以作用於Number之間、String之間、Pattern之間、Boolean之間、變數之間以及其他型別與nil之間的關係比較,不同型別除了nil之外不能相互比較。

Aviator規定任何物件都比nil大除了nil之外。

匹配運算子

匹配運算子"=~"用於String和Pattern的匹配,它的左運算元必須為String,右運算元必須為Pattern。匹配成功後,Pattern的分組將存於變數$num,num為分組索引。

三元運算子

Aviator沒有提供if else語句,但是提供了三元運算子 "?:",形式為 bool ? exp1: exp2。 其中bool必須為結果為Boolean型別的表示式,而exp1和exp2可以為任何合法的Aviator表示式,並且不要求exp1和exp2返回的結果型別一致。

  1. 兩種模式
    預設AviatorEvaluator以編譯速度優先:
    AviatorEvaluator.setOptimize(AviatorEvaluator.COMPILE);
    你可以修改為執行速度優先,這會做更多的編譯優化:
    AviatorEvaluator.setOptimize(AviatorEvaluator.EVAL);

三.MVEL表示式解析器

1.簡介 :

MVEL在很大程度上受到Java語法的啟發,作為一個表示式語言,也有一些根本
的區別,旨在更高的效率,例如:直接支援集合、陣列和字串匹配等操作以
及正規表示式。 MVEL用於執行使用Java語法編寫的表示式。

2.特性:

MVEL是一個功能強大的基於Java應用程式的表示式語言。
目前最新的版本是2.0,具有以下特性:
(1). 動態JIT優化器。當負載超過一個確保程式碼產生的閾值時,選擇性地產生字
節程式碼,這大大減少了記憶體的使用量。新的靜態型別檢查和屬性支援,允許整合
型別安全表達。
(2). 錯誤報告的改善。包括行和列的錯誤資訊。
(3). 新的指令碼語言特徵。MVEL2.0 包含函式定義,如:閉包,lambda定義,
標準迴圈構造(for, while, do-while, do-until…),空值安全導航操作,內聯with
-context運營 ,易變的(isdef)的測試運營等等。
(4). 改進的整合功能。迎合主流的需求,MVEL2.0支援基礎型別的個性化屬性處理器,整合到JIT中。
(5). 更快的模板引擎,支援線性模板定義,巨集定義和個性化標記定義。
(6). 新的互動式shell(MVELSH)。

(7). 缺少可選型別安全
(8). 整合不良,通常通過對映填入內容。沒有位元組碼不能運作用位元組碼生成編
譯時間慢,還增加了可擴充套件性問題;不用位元組碼生成執行時執行非常慢
(9). 記憶體消耗過大
(10). Jar巨大/依賴規模

3.原理:

與java不同,MVEL是動態型別(帶有可選分類),也就是說在原始檔中是沒有
型別限制的。一條MVEL表示式,簡單的可以是單個識別符號,複雜的則可能是
一個充滿了方法呼叫和內部集合建立的龐大的布林表示式。

4.使用方式:
maven引入jar:

<dependency>
            <groupId>org.mvel</groupId>
            <artifactId>mvel2</artifactId>
            <version>2.3.1.Final</version>
        </dependency>

測試:

package com.lrq.wechatdemo.utils;

import com.google.common.collect.Maps;
import org.mvel2.MVEL;

import java.util.Map;

/**
 * CreateBy: Liurenquan
 * CreateDate: 2018/12/26
 */
public class MvelUtils {

    public static void main(String[] args) {
        String expression = "a == null && b == nil ";
        Map<String,Object> map = Maps.newHashMap();
        map.put("a",null);
        map.put("b",null);

        Object object = MVEL.eval(expression,map);
        System.out.println(object);
    }

}

四.EasyRules規則引擎

1.簡介:

easy-rules首先整合了mvel表示式,後續可能整合SpEL的一款輕量
級規則引擎

2.特性:

easy rules是一個簡單而強大的java規則引擎,它有以下特性:

輕量級框架,學習成本低
基於POJO
為定義業務引擎提供有用的抽象和簡便的應用
從原始的規則組合成複雜的規則
它主要包括幾個主要的類或介面:Rule,RulesEngine,RuleListener,Facts 
還有幾個主要的註解:@Action,@Condition,@Fact,@Priority,@Rule

3.使用方式:

@Rule可以標註name和description屬性,每個rule的name要唯一,
如果沒有指定,則RuleProxy則預設取類名
@Condition是條件判斷,要求返回boolean值,表示是否滿足條件

@Action標註條件成立之後觸發的方法

@Priority標註該rule的優先順序,預設是Integer.MAX_VALUE - 1,值
越小越優先

@Fact 我們要注意Facts的使用。Facts的用法很像Map,它是客戶
端和規則檔案之間通訊的橋樑。在客戶端使用put方法向Facts中添
加資料,在規則檔案中通過key來得到相應的資料。

有兩種使用方式:

  1. java方式
    首先先建立規則並標註屬性
package com.lrq.wechatdemo.rules;

import org.jeasy.rules.annotation.Action;
import org.jeasy.rules.annotation.Condition;
import org.jeasy.rules.annotation.Fact;
import org.jeasy.rules.annotation.Rule;
import org.jeasy.rules.support.UnitRuleGroup;

/**
 * CreateBy: Liurenquan
 * CreateDate: 2018/12/26
 */
public class RuleClass {

    @Rule(priority = 1) //規則設定優先順序
    public static class FizzRule {
        @Condition
        public boolean isFizz(@Fact("number") Integer number) {
            return number % 5 == 0;
        }

        @Action
        public void printFizz() {
            System.out.print("fizz\n");
        }
    }

    @Rule(priority = 2)
    public static class BuzzRule {
        @Condition
        public boolean isBuzz(@Fact("number") Integer number) {
            return number % 7 == 0;
        }

        @Action
        public void printBuzz() {
            System.out.print("buzz\n");
        }
    }

    public static class FizzBuzzRule extends UnitRuleGroup {

        public FizzBuzzRule(Object... rules) {
            for (Object rule : rules) {
                addRule(rule);
            }
        }

        @Override
        public int getPriority() {
            return 0;
        }
    }

    @Rule(priority = 3)
    public static class NonFizzBuzzRule {

        @Condition
        public boolean isNotFizzNorBuzz(@Fact("number") Integer number) {
            // can return true, because this is the latest rule to trigger according to
            // assigned priorities
            // and in which case, the number is not fizz nor buzz
            return number % 5 != 0 || number % 7 != 0;
        }

        @Action
        public void printInput(@Fact("number") Integer number) {
            System.out.print(number+"\n");
        }
    }

}

然後客戶端呼叫

package com.lrq.wechatdemo.rules;

import org.jeasy.rules.api.Facts;
import org.jeasy.rules.api.Rules;
import org.jeasy.rules.api.RulesEngine;
import org.jeasy.rules.core.DefaultRulesEngine;
import org.jeasy.rules.core.RulesEngineParameters;

/**
 * CreateBy: Liurenquan
 * CreateDate: 2018/12/26
 */
public class RuleJavaClient {
    public static void main(String[] args) {
        // 建立規則引擎
        RulesEngineParameters parameters = new RulesEngineParameters().skipOnFirstAppliedRule(true);
        RulesEngine fizzBuzzEngine = new DefaultRulesEngine(parameters);

        // 建立規則集並註冊規則
        Rules rules = new Rules();
        rules.register(new RuleClass.FizzRule());
        rules.register(new RuleClass.BuzzRule());
        rules.register(new RuleClass.FizzBuzzRule(new RuleClass.FizzRule(), new RuleClass.BuzzRule()));
        rules.register(new RuleClass.NonFizzBuzzRule());

        // 執行規則
        Facts facts = new Facts();
        for (int i = 1; i <= 100; i++) {
            facts.put("number", i);
            fizzBuzzEngine.fire(rules, facts);
            System.out.println();
        }
    }

}

2.yml方式

resources目錄下新建fizzbuzz.yml

---
name: "fizz rule"
description: "print fizz if the number is multiple of 5"
priority: 1
condition: "number % 5 == 0"
actions:
- "System.out.println(\"fizz\")"

---
name: "buzz rule"
description: "print buzz if the number is multiple of 7"
priority: 2
condition: "number % 7 == 0"
actions:
- "System.out.println(\"buzz\")"

---
name: "fizzbuzz rule"
description: "print fizzbuzz if the number is multiple of 5 and 7"
priority: 0
condition: "number % 5 == 0 && number % 7 == 0"
actions:
- "System.out.println(\"fizzbuzz\")"

---
name: "non fizzbuzz rule"
description: "print the number itself otherwise"
priority: 3
condition: "number % 5 != 0 || number % 7 != 0"
actions:
- "System.out.println(number)"

客戶端呼叫:

package com.lrq.wechatdemo.rules;

import org.jeasy.rules.api.Facts;
import org.jeasy.rules.api.Rules;
import org.jeasy.rules.api.RulesEngine;
import org.jeasy.rules.core.DefaultRulesEngine;
import org.jeasy.rules.core.RulesEngineParameters;
import org.jeasy.rules.mvel.MVELRuleFactory;

import java.io.FileNotFoundException;
import java.io.FileReader;

/**
 * CreateBy: Liurenquan
 * CreateDate: 2018/12/26
 */
public class RuleYmlClient {

    public static void main(String[] args) throws FileNotFoundException {
        // create a rules engine
        RulesEngineParameters parameters = new RulesEngineParameters().skipOnFirstAppliedRule(true);
        RulesEngine fizzBuzzEngine = new DefaultRulesEngine(parameters);

        // create rules
        Rules rules = MVELRuleFactory.createRulesFrom(new FileReader("fizzbuzz.yml"));

        // fire rules
        Facts facts = new Facts();
        for (int i = 1; i <= 100; i++) {
            facts.put("number", i);
            fizzBuzzEngine.fire(rules, facts);
            System.out.println();
        }
    }
}

 

相關文章