規則引擎由推理引擎發展而來,是一種嵌入在應用程序中的組件,實現了將業務決策從應用程序代碼中分離出來,並使用預定義的語義模塊編寫業務決策。
規則引擎具體執行可以分為接受數據輸入,解釋業務規則,根據業務規則做出業務決策幾個過程。
使用規則引擎可以把復雜、冗余的業務規則同整個支撐系統分離開,做到架構的可復用移植。
規則引擎的應用
相對於業務系統,規則引擎可以認為是一個獨立於業務系統的模塊,負責一些規則的計算等。
一般來說,規則引擎主要應用在下面的場景中:
- 風控模型配置,風控是規則引擎
- 用戶積分等配置,如日常操作引起積分變化等
- 簡單的離線計算,各類數據量比較小的統計等
常用規則引擎的選型
目前的規則引擎系統中,使用較多的開源規則引擎是Drools,另外還有商用的規則管理系統BRMS是ILOG JRules。
Drools
Drools是一個基於Java的開源規則引擎,可以將復雜多變的規則從硬編碼中解放出來,以規則腳本的形式存放在文件中,使得規則的變更不需要修正代碼重啟機器就可以立即在線上環境生效。
目前版本是5.0.1,Drools從5.0后分為四個模塊:
- Drools Guvnor (BRMS/BPMS)
- Drools Expert (rule engine)
- Drools Flow (process/workflow)
- Drools Fusion (cep/temporal reasoning)
[drools應用文檔](https://github.com/kiegroup/droolsjbpm-build-bootstrap/blob/master/README.md
)
Ilog JRules
Ilog Jrules是完整的業務規則管理系統(BRMS),它提供了對整個企業業務規則進行建模、編寫、測試、部署和維護所必需的所有工具。
Ilog Jrules主要包括以下4個組件:
- Rule Studio(RS) 面向開發人員使用的開發環境,用於規則的建模和編寫
- Rule Scenario Manager 規則測試工具
- Rule Team Server(RTS) 基於Web的管理環境,面向業務人員使用,用於規則發布、管理、存儲
- Rule Execution Server(RES) 面向運維人員使用,用於規則執行、監控
[Ilog Jrules主頁](https://www-01.ibm.com/software/integration/business-rule-management/jrules-family/
)
這兩款規則引擎設計和實現都比較復雜,學習成本高,適用於大型應用系統。
Easy Rules
Easy Rules是我偶然間看到的一個規則引擎實現,相比Drools等企業級規則引擎,Easy Rules的應用非常簡單,學習成本低,容易上手。
下面重點介紹這款輕量級的規則引擎 Easy Rules。
輕量級規則引擎Easy Rules
Easy Rules官方主頁:http://www.easyrules.org/
Easy Rules提供以下功能:
- 輕量級框架和易於學習的API
- 基於POJO的開發
- 通過高效的抽象來定義業務規則並輕松應用它們
- 支持創建復合規則
Easy Rules的應用
Easy rules的工程可以從Github下載,構建需要Maven支持。
$ git clone https://github.com/EasyRules/easyrules.git
$ cd easyrules
$ mvn install
Easy Rules打包后是一個單獨的jar,使用時需要添加相關文件到工程中,或者添加Maven依賴:
<dependency>
<groupId>org.easyrules</groupId>
<artifactId>easyrules-core</artifactId>
<version>2.4.0</version>
</dependency>
配置你的業務規則
大多數業務規則可以表示為以下定義:
- 名稱:一種唯一的規則名稱
- 描述:對規則的簡要描述
- 優先級:相對於其他規則的優先級
- 條件:設置規則執行時需要滿足的條件
- 操作:設置的條件滿足時執行的操作
我們可以通過擴展Easy Rules提供的Rule interface來定義規則,或者通過注解,定義自己的規則類。
下面是內置的Rule接口:
package org.easyrules.api;
public interface Rule {
<span class="hljs-comment">/**
* 這個方法定義了規則執行的條件
* <span class="hljs-doctag">@return</span> true if the rule should be applied, false else
*/</span>
<span class="hljs-function"><span class="hljs-keyword">boolean</span> <span class="hljs-title">evaluate</span><span class="hljs-params">()</span></span>;
<span class="hljs-comment">/**
* 這個方法定義了規則執行的具體動作
* <span class="hljs-doctag">@throws</span> Exception if an error occurs
*/</span>
<span class="hljs-function"><span class="hljs-keyword">void</span> <span class="hljs-title">execute</span><span class="hljs-params">()</span> <span class="hljs-keyword">throws</span> Exception</span>;
<span class="hljs-comment">//Getters and setters for rule name,</span>
<span class="hljs-comment">//description and priority omitted.</span>
}
創建規則引擎
Easy Rules的引擎實例會維護一個不同規則的注冊空間,每個Engine可以被視為一個單獨的名稱空間。
多條規則將會按照他們的自然順序去執行,也就是默認的優先級。
要創建一個規則引擎和注冊規則,可以使用下面的靜態方法:
RulesEngineBuilder.aNewEngineBuilder():
RulesEngine rulesEngine = aNewEngineBuilder().build();
rulesEngine.registerRule(myRule);
執行下面的操作啟動規則執行:
rulesEngine.fireRules();
Easy Rules應用實例
下面通過一個簡單的Hello World示例來展示Easy Rules的具體應用。
通過注解創建一個具體的規則類:
@Rule(name = "Hello World rule",
description = "Say Hello to duke's friends only")
public class HelloWorldRule {
<span class="hljs-comment">/**
* The user input which represents the data
* that the rule will operate on.
*/</span>
<span class="hljs-keyword">private</span> String input;
<span class="hljs-meta">@Condition</span>
<span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">boolean</span> <span class="hljs-title">checkInput</span><span class="hljs-params">()</span> </span>{
<span class="hljs-comment">//The rule should be applied only if</span>
<span class="hljs-comment">//the user's response is yes (duke friend)</span>
<span class="hljs-keyword">return</span> input.equalsIgnoreCase(<span class="hljs-string">"yes"</span>);
}
<span class="hljs-meta">@Action</span>
<span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">sayHelloToDukeFriend</span><span class="hljs-params">()</span> <span class="hljs-keyword">throws</span> Exception </span>{
<span class="hljs-comment">//When rule conditions are satisfied,</span>
<span class="hljs-comment">//prints 'Hello duke's friend!' to the console</span>
System.out.println(<span class="hljs-string">"Hello duke's friend!"</span>);
}
<span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">setInput</span><span class="hljs-params">(String input)</span> </span>{
<span class="hljs-keyword">this</span>.input = input;
}
}
接下來創建一個規則引擎的實例,注冊並且啟動這個規則:
public class Launcher {
<span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span> <span class="hljs-title">main</span>(<span class="hljs-params">String[] args</span>) </span>{
Scanner scanner = <span class="hljs-keyword">new</span> Scanner(System.<span class="hljs-keyword">in</span>);
System.<span class="hljs-keyword">out</span>.println(<span class="hljs-string">"Are you a friend of duke?[yes/no]:"</span>);
String input = scanner.nextLine();
<span class="hljs-comment">/**
* Declare the rule
*/</span>
HelloWorldRule helloWorldRule = <span class="hljs-keyword">new</span> HelloWorldRule();
<span class="hljs-comment">/**
* Set business data to operate on
*/</span>
helloWorldRule.setInput(input.trim());
<span class="hljs-comment">/**
* Create a rules engine and register the business rule
*/</span>
RulesEngine rulesEngine = aNewRulesEngine().build();
rulesEngine.registerRule(helloWorldRule);
<span class="hljs-comment">/**
* Fire rules
*/</span>
rulesEngine.fireRules();
}
}
規則啟動后會通過一個簡單的條件判斷(控制台輸入),然后執行接下來的動作(輸出規則信息)。
除了規則引擎基礎的規則執行功能, Easy Rules還支持監聽規則執行情況,為規則執行配置調度器,
集成Spring等功能。
關於規則引擎的選型和簡單應用就介紹到這里,除了風控等大型的應用系統,一些獨立的小型產品需求中,可以合理應用規則引擎實現業務與規則的分離,降低系統間耦合,上面介紹的Easy Rules就是一個不錯的選擇。
<!-- 登錄查看 begin -->
<!-- 登錄查看 end -->
</div>