规则引擎Easy-rules
官網源碼:https://github.com/j-easy/easy-rules
官網案例:https://github.com/j-easy/easy-rules/wiki/fizz-buzz
介紹:
規則引擎是為了解決業務代碼和業務規則分離的引擎,是一種嵌入在應用程序中的組件,實現了將業務決策從應用程序代碼中分離,其實就是將一大堆if/else進行處理,Easy Rules 所做的,它提供了Rule創建具有條件和操作的規則的抽象,以及RulesEngine通過一組規則運行以評估條件和執行操作的API
核心功能:
一個規則由名稱、描述、優先級三個屬性和判斷、執行兩個方法組成,實現Rule接口,
和使用@Rule,@Condition,@Action,@Priority,@Fact注解的效果是一樣的。
它主要包括幾個主要的類或接口:Rule,RulesEngine,RuleListener,Facts
還有幾個主要的注解:@Action,@Condition,@Fact,@Priority,@Rule
(定義規則監聽器通過實現RuleListener接口)
一. pom.xml中引入maven依賴
<!--easy rules核心庫--> <dependency><groupId>org.jeasy</groupId><artifactId>easy-rules-core</artifactId><version>4.0.0</version> </dependency><!--規則定義文件格式,支持json,yaml等--> <dependency><groupId>org.jeasy</groupId><artifactId>easy-rules-support</artifactId><version>4.0.0</version> </dependency><!--支持mvel規則語法庫--> <dependency><groupId>org.jeasy</groupId><artifactId>easy-rules-mvel</artifactId><version>4.0.0</version> </dependency>二. 定義規則
大多數業務規則可以由以下定義表示:
Easy Rules為定義業務規則的每個關鍵點提供了抽象。
public interface Rule {/*** 改方法封裝規則的條件(conditions)* @return 如果提供的事實適用于該規則返回true, 否則,返回false*/boolean evaluate(Facts facts);/*** 改方法封裝規則的操作(actions)* @throws 如果在執行過程中發生錯誤將拋出Exception*/void execute(Facts facts) throws Exception;//Getters and setters for rule name, description and priority omitted.}evaluate方法封裝了必須求值為TRUE才能觸發規則的條件。
execute方法封裝了在滿足規則條件時應執行的操作。條件和動作ConditionandAction接口表示。
首先,定義規則,方式有多種
方式一:注解
@Condition注解標記計算規則條件的方法。此方法必須是公共的,可以有一個或多個用@Fact注解的參數,并返回布爾類型。只有一個方法能用@Condition注解。
@Action注解標記要執行規則操作的方法。規則可以有多個操作。可以使用order屬性按指定的順序執行操作。默認情況下,操作的順序為0。
方式二:鏈式編程
Rule rule = new RuleBuilder().name("myRule").description("myRuleDescription").priority(3).when(condition).then(action1).then(action2).build();在這個例子中, Condition實例condition,Action實例是action1和action2。
方式三:表達式
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
組合規則
CompositeRule由一組規則組成。這是一個典型地組合設計模式的實現。
組合規則是一個抽象概念,因為可以以不同方式觸發組合規則。
Easy Rules自帶三種CompositeRule實現:
UnitRuleGroup : 要么應用所有規則,要么不應用任何規則(AND邏輯)
ActivationRuleGroup : 它觸發第一個適用規則,并忽略組中的其他規則(XOR邏輯)
ConditionalRuleGroup : 如果具有最高優先級的規則計算結果為true,則觸發其余規則
復合規則可以從基本規則創建并注冊為常規規則:
每個規則都有優先級。它代表觸發注冊規則的默認順序。默認情況下,較低的值表示較高的優先級。可以重寫compareTo方法以提供自定義優先級策略。
定義事實
Facts API是一組事實的抽象,在這些事實上檢查規則。
在內部,Facts實例持有HashMap<String,Object>,這意味著:
事實需要命名,應該有一個唯一的名稱,且不能為空
任何Java對象都可以充當事實
這里有一個實例定義事實:
用@Fact注解可以將Facts注入到condition和action方法中
在下面的規則中,rain 事實被注入itRains方法的rain參數:
Facts類型參數 被注入已知的 facts中 (像action方法takeAnUmbrella一樣).
如果缺少注入的fact, 這個引擎會拋出 RuntimeException異常.
定義規則引擎
從版本3.1開始,Easy Rules提供了RulesEngine接口的兩種實現:
創建一個規則引擎
要創建規則引擎,可以使用每個實現的構造函數:
然后,您可以按以下方式觸發注冊規則:
rulesEngine.fire(rules, facts);規則引擎參數
Easy Rules 引擎可以配置以下參數:
Parameter Type Required Default rulePriorityThreshold int no MaxInt skipOnFirstAppliedRule boolean no false skipOnFirstFailedRule boolean no false skipOnFirstNonTriggeredRule boolean no falseskipOnFirstAppliedRule:告訴引擎規則被觸發時跳過后面的規則。
skipOnFirstFailedRule:告訴引擎在規則失敗時跳過后面的規則。
skipOnFirstNonTriggeredRule:告訴引擎一個規則不會被觸發跳過后面的規則。
rulePriorityThreshold:告訴引擎如果優先級超過定義的閾值,則跳過下一個規則。版本3.3已經不支持更改,默認MaxInt。
可以使用RulesEngineParameters API指定這些參數:
如果要從引擎獲取參數,可以使用以下代碼段:
RulesEngineParameters parameters = myEngine.getParameters();這允許您在創建引擎后重置引擎參數。
開始測試案例
1.創建項目(通過maven骨架創建)
創建完成后,會默認生成一個HelloWorldRule規則
入過啟動報錯 Error:(26, 34) java: 程序包org.jeasy.rules.annotation不存在
File -->settings —>maven —>Runner ,勾選:Dele… 然后保存
重寫啟動
依賴:
測試案例一:
1.用到的實體
package org.testRule.one;/*** @author: YXY* @date: 2021/6/23 15:22* @Version 1.0*/ public class User {private Integer age;public Integer getAge() {return age;}public void setAge(Integer age) {this.age = age;} }2.測試類
package org.testRule.one;import org.jeasy.rules.annotation.Rule; 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.mvel.MVELRule;import java.util.HashMap; import java.util.Map;/*** @author: YXY* @date: 2021/6/23 15:21* @Version 1.0*/ public class MVELTestRule {public static void main(String[] args) {//規則引擎RulesEngine rulesEngine = new DefaultRulesEngine();//規則MVELRule ageRule = new MVELRule().name("my rule").description("test demo rule").priority(1).when("user.age > 18").then("map.put('code',200);map.put('msg','success');");Rules rules = new Rules();rules.register(ageRule);Facts facts = new Facts();User user = new User();user.setAge(19);facts.put("user",user);Map map = new HashMap();facts.put("map",map);rulesEngine.fire(rules,facts);System.out.println(map);} }3.運行結果
測試案例二:
1.定義規則
2.測試類
package org.testRule.tow;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.testRule.tow.rules.OtherRule; import org.testRule.tow.rules.ThreeRule; import org.testRule.tow.rules.TwoRule; import org.testRule.tow.rules.TwoThreeRuleUnitGroup;/*** @author: YXY* @date: 2021/6/23 15:21* @Version 1.0*/public class RuleTest {public static void main(String[] args) {RulesEngine rulesEngine = new DefaultRulesEngine();//創建規則Rules rules = new Rules();rules.register(new TwoRule());rules.register(new ThreeRule());rules.register(new TwoThreeRuleUnitGroup(new TwoRule(), new ThreeRule()));rules.register(new OtherRule());//設置真實數據Facts facts = new Facts();for (int i=1 ; i<=10 ; i++){//規則因素,對應的name,要和規則里面的@Fact 一致facts.put("num", i);//執行規則rulesEngine.fire(rules, facts);System.out.println();}} }3.運行結果
控制臺亂碼解決:
總結
以上是生活随笔為你收集整理的规则引擎Easy-rules的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 天府通如何设置支付顺序(四川天府新区管委
- 下一篇: 部落冲突api令牌干什么用的 《部落冲突