歡迎您光臨本站 註冊首頁

Java規則引擎Easy Rules的使用介紹

←手機掃碼閱讀     ml5rwbikls @ 2020-06-12 , reply:0

1. Easy Rules 概述

Easy Rules是一個Java規則引擎,靈感來自一篇名為《Should I use a Rules Engine?》的文章

規則引擎就是提供一種可選的計算模型。與通常的命令式模型(由帶有條件和循環的命令依次組成)不同,規則引擎基於生產規則系統。這是一組生產規則,每條規則都有一個條件(condition)和一個動作(action)―――― 簡單地說,可以將其看作是一組if-then語句。

精妙之處在於規則可以按任何順序編寫,引擎會決定何時使用對順序有意義的任何方式來計算它們。考慮它的一個好方法是系統運行所有規則,選擇條件成立的規則,然後執行相應的操作。這樣做的好處是,很多問題都很自然地符合這個模型:

if car.owner.hasCellPhone then premium += 100;
 if car.model.theftRating > 4 then premium += 200;
 if car.owner.livesInDodgyArea && car.model.theftRating > 2 then premium += 300;

規則引擎是一種工具,它使得這種計算模型編程變得更容易。它可能是一個完整的開發環境,或者一個可以在傳統平臺上工作的框架。生產規則計算模型最適合僅解決一部分計算問題,因此規則引擎可以更好地嵌入到較大的系統中。

你可以自己構建一個簡單的規則引擎。你所需要做的就是創建一組帶有條件和動作的對象,將它們存儲在一個集合中,然後遍歷它們以評估條件並執行這些動作。

Easy Rules它提供Rule抽象以創建具有條件和動作的規則,並提供RuleEngine API,該API通過一組規則運行以評估條件並執行動作。

Easy Rules簡單易用,只需兩步:

首先,定義規則,方式有很多種

方式一:註解

  @Rule(name = "weather rule", description = "if it rains then take an umbrella")  public class WeatherRule {      @Condition    public boolean itRains(@Fact("rain") boolean rain) {      return rain;    }        @Action    public void takeAnUmbrella() {      System.out.println("It rains, take an umbrella!");    }  }

 

方式二:鏈式編程

  Rule weatherRule = new RuleBuilder()      .name("weather rule")      .description("if it rains then take an umbrella")      .when(facts -> facts.get("rain").equals(true))      .then(facts -> System.out.println("It rains, take an umbrella!"))      .build();

 

方式三:表達式

  Rule weatherRule = new MVELRule()      .name("weather rule")      .description("if it rains then take an umbrella")      .when("rain == true")      .then("System.out.println("It rains, take an umbrella!");");

 

方式四:yml配置文件

例如:weather-rule.yml

  name: "weather rule"  description: "if it rains then take an umbrella"  condition: "rain == true"  actions:   - "System.out.println("It rains, take an umbrella!");"

 

  MVELRuleFactory ruleFactory = new MVELRuleFactory(new YamlRuleDefinitionReader());  Rule weatherRule = ruleFactory.createRule(new FileReader("weather-rule.yml"));

 

接下來,應用規則

  public class Test {    public static void main(String[] args) {      // define facts      Facts facts = new Facts();      facts.put("rain", true);        // define rules      Rule weatherRule = ...      Rules rules = new Rules();      rules.register(weatherRule);        // fire rules on known facts      RulesEngine rulesEngine = new DefaultRulesEngine();      rulesEngine.fire(rules, facts);    }  }

 

入門案例:Hello Easy Rules

  org.jeasyeasy-rules-core4.0.0

 

通過骨架創建maven項目:

  mvn archetype:generate     -DarchetypeGroupId=org.jeasy     -DarchetypeArtifactId=easy-rules-archetype     -DarchetypeVersion=4.0.0

 

默認給我們生成了一個HelloWorldRule規則,如下:

  package com.cjs.example.rules;    import org.jeasy.rules.annotation.Action;  import org.jeasy.rules.annotation.Condition;  import org.jeasy.rules.annotation.Rule;    @Rule(name = "Hello World rule", description = "Always say hello world")  public class HelloWorldRule {      @Condition    public boolean when() {      return true;    }      @Action    public void then() throws Exception {      System.out.println("hello world");    }    }

 

2. 規則定義

2.1. 定義規則

大多數業務規則可以用以下定義表示:

  • Name : 一個命名空間下的唯一的規則名稱

  • Description : 規則的簡要描述

  • Priority : 相對於其他規則的優先級

  • Facts : 事實,可立即為要處理的數據

  • Conditions : 為了應用規則而必須滿足的一組條件

  • Actions : 當條件滿足時執行的一組動作

Easy Rules為每個關鍵點提供了一個抽象來定義業務規則。

在Easy Rules中,Rule接口代表規則

  public interface Rule {      /**    * This method encapsulates the rule's conditions.    * @return true if the rule should be applied given the provided facts, false otherwise    */    boolean evaluate(Facts facts);      /**    * This method encapsulates the rule's actions.    * @throws Exception if an error occurs during actions performing    */    void execute(Facts facts) throws Exception;      //Getters and setters for rule name, description and priority omitted.    }

 

evaluate方法封裝了必須計算結果為TRUE才能觸發規則的條件。execute方法封裝了在滿足規則條件時應該執行的動作。條件和操作由Condition和Action接口表示。

定義規則有兩種方式:

  • 通過在POJO類上添加註解

  • 通過RuleBuilder API編程

可以在一個POJO類上添加@Rule註解,例如:

  @Rule(name = "my rule", description = "my rule description", priority = 1)  public class MyRule {      @Condition    public boolean when(@Fact("fact") fact) {      //my rule conditions      return true;    }      @Action(order = 1)    public void then(Facts facts) throws Exception {      //my actions    }      @Action(order = 2)    public void finally() throws Exception {      //my final actions    }  }

 

@Condition註解指定規則條件
 @Fact註解指定參數
 @Action註解指定規則執行的動作

RuleBuilder支持鏈式風格定義規則,例如:

  Rule rule = new RuleBuilder()          .name("myRule")          .description("myRuleDescription")          .priority(3)          .when(condition)          .then(action1)          .then(action2)          .build();

 

組合規則

CompositeRule由一組規則組成。這是一個典型地組合設計模式的實現。

組合規則是一個抽象概念,因為可以以不同方式觸發組合規則。

Easy Rules自帶三種CompositeRule實現:

  • UnitRuleGroup : 要麼應用所有規則,要麼不應用任何規則(AND邏輯)

  • ActivationRuleGroup : 它觸發第一個適用規則,並忽略組中的其他規則(XOR邏輯)

  • ConditionalRuleGroup : 如果具有最高優先級的規則計算結果為true,則觸發其餘規則

複合規則可以從基本規則創建並註冊為常規規則:

  //Create a composite rule from two primitive rules  UnitRuleGroup myUnitRuleGroup = new UnitRuleGroup("myUnitRuleGroup", "unit of myRule1 and myRule2");  myUnitRuleGroup.addRule(myRule1);  myUnitRuleGroup.addRule(myRule2);    //Register the composite rule as a regular rule  Rules rules = new Rules();  rules.register(myUnitRuleGroup);    RulesEngine rulesEngine = new DefaultRulesEngine();  rulesEngine.fire(rules, someFacts);

 

每個規則都有優先級。它代表觸發註冊規則的默認順序。默認情況下,較低的值表示較高的優先級。可以重寫compareTo方法以提供自定義優先級策略。

2.2. 定義事實

在Easy Rules中,Fact API代表事實

  public class Fact{     private final String name;     private final T value;  }

 

舉個栗子:

  Factfact = new Fact("foo", "bar");  Facts facts = new Facts();  facts.add(fact);

 

或者,也可以用這樣簡寫形式

  Facts facts = new Facts();  facts.put("foo", "bar");

 

用@Fact註解可以將Facts注入到condition和action方法中

  @Rule  class WeatherRule {      @Condition    public boolean itRains(@Fact("rain") boolean rain) {      return rain;    }      @Action    public void takeAnUmbrella(Facts facts) {      System.out.println("It rains, take an umbrella!");      // can add/remove/modify facts    }    }

 

2.3. 定義規則引擎

Easy Rules提供兩種RulesEngine接口實現:

  • DefaultRulesEngine : 根據規則的自然順序應用規則

  • InferenceRulesEngine : 持續對已知事實應用規則,直到不再適用任何規則為止

創建規則引擎:

  RulesEngine rulesEngine = new DefaultRulesEngine();    // or    RulesEngine rulesEngine = new InferenceRulesEngine();

 

然後,註冊規則

  rulesEngine.fire(rules, facts);

 

規則引擎有一些可配置的參數,如下圖所示:

舉個栗子:

  RulesEngineParameters parameters = new RulesEngineParameters()    .rulePriorityThreshold(10)    .skipOnFirstAppliedRule(true)    .skipOnFirstFailedRule(true)    .skipOnFirstNonTriggeredRule(true);    RulesEngine rulesEngine = new DefaultRulesEngine(parameters);

 

2.4. 定義規則監聽器

通過實現RuleListener接口

  public interface RuleListener {      /**     * Triggered before the evaluation of a rule.     *     * @param rule being evaluated     * @param facts known before evaluating the rule     * @return true if the rule should be evaluated, false otherwise     */    default boolean beforeEvaluate(Rule rule, Facts facts) {      return true;    }      /**     * Triggered after the evaluation of a rule.     *     * @param rule that has been evaluated     * @param facts known after evaluating the rule     * @param evaluationResult true if the rule evaluated to true, false otherwise     */    default void afterEvaluate(Rule rule, Facts facts, boolean evaluationResult) { }      /**     * Triggered on condition evaluation error due to any runtime exception.     *     * @param rule that has been evaluated     * @param facts known while evaluating the rule     * @param exception that happened while attempting to evaluate the condition.     */    default void onEvaluationError(Rule rule, Facts facts, Exception exception) { }      /**     * Triggered before the execution of a rule.     *     * @param rule the current rule     * @param facts known facts before executing the rule     */    default void beforeExecute(Rule rule, Facts facts) { }      /**     * Triggered after a rule has been executed successfully.     *     * @param rule the current rule     * @param facts known facts after executing the rule     */    default void onSuccess(Rule rule, Facts facts) { }      /**     * Triggered after a rule has failed.     *     * @param rule the current rule     * @param facts known facts after executing the rule     * @param exception the exception thrown when attempting to execute the rule     */    default void onFailure(Rule rule, Facts facts, Exception exception) { }    }

 

3. 示例

  4.0.0com.cjs.exampleeasy-rules-quickstart1.0.0-SNAPSHOTjarorg.jeasyeasy-rules-core4.0.0org.jeasyeasy-rules-support4.0.0org.jeasyeasy-rules-mvel4.0.0org.slf4jslf4j-simple1.7.30

 

4. 擴展

規則本質上是一個函數,如y=f(x1,x2,..,xn)

規則引擎就是為了解決業務代碼和業務規則分離的引擎,是一種嵌入在應用程序中的組件,實現了將業務決策從應用程序代碼中分離。

還有一種常見的方式是Java+Groovy來實現,Java內嵌Groovy腳本引擎進行業務規則剝離。

https://github.com/j-easy/easy-rules/wiki



[ml5rwbikls ] Java規則引擎Easy Rules的使用介紹已經有276次圍觀

http://coctec.com/docs/java/show-post-238306.html