Drools: 基於Java的Business Rule Engine

簡介與範例執行流程分享

邱奕修
8 min readDec 13, 2022

最近因計畫需要survey CEP(Complex Event Processing) 相關技術,該領域中比較有名有聽過的應該是Esper,然而在看過一些會議論文後,發現近兩年蠻多人用Drools 來實現CEP,較新的技術且資源也蠻充沛的(user guide, 書籍…),就該來花點時間研究一下啦~

業務規則引擎 — Drools

Drools 是JBoss(後來被Red Hat收購) 維護的開源項目之一,是基於Java並以Rete 演算法來實現的規則引擎,主要目標為將業務邏輯ㄧ切割出來,降低程式與業務邏輯的耦合(Coupling)。在Drools 6.0之後,可以透過KIE API 來更簡便地操作Drools,其結構如下圖:

KIE (Knowledge Is Everything) 結構

底下將以一個簡單範例展示Drools 的安裝設定流程與其基本功能。

新建Maven專案:

首先,建立一Maven 專案,並在resources 資料夾下新增”META-INF”與”rules”資料夾,其中”META-INF”資料夾下會放置kmodule 的設定檔,而”rules”下則是放我們要撰寫的業務規則檔案。

專案目錄結構

引用Drools套件:

在專案中的pom.xml 中加入以下內容並執行Maven reload 來安裝Drools 相關的jar 包:

<properties>
<drools.version>7.10.0.Final</drools.version>
</properties>

<dependencies>
<dependency>
<groupId>org.drools</groupId>
<artifactId>drools-compiler</artifactId>
<version>${drools.version}</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.11</version>
</dependency>
</dependencies>

撰寫業務規則:

為了展示範例,在撰寫Drools 規則檔之前,我們需要先建立一個基本的Java類別,範例類別如下:

public class Person {
private String name;
private int age;

public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}

接著就是Drools 規則檔了,在本範例中,我們要撰寫一個年齡分層的規則。首先,在前面創建的”rules”資料夾下建立”test.drl”並填入以下內容:

package rules
// 引入Person類別
import com.pojo.Person

rule "rule0"
when
$p:Person(age>=12);
then
System.out.println($p.getName()+"的年齡大於12歲");
end

rule "rule1"
when
$p:Person(age>=18);
then
System.out.println($p.getName()+"的年齡大於18歲");
end

rule "rule2"
when
$p:Person(age>=20);
then
System.out.println($p.getName()+"的年齡大於20歲");
end

上面內容包含三個rule,每個rule由”rule”開頭”end”結尾,中間以”when”與”then”來將規則劃分成兩部分:

  • when 部分(稱作Left Hand Side, LHS):

就像是if 判斷式的條件一般,裡面可以撰寫0到多個條件(若沒有條件則default為true),若全部條件皆為true 則執行then 內容,false 則不執行。

  • then 部分(稱作Right Hand Side, RHS):

只有LHS 內條件全部成立才會被執行,內容可以撰寫任何Java 程式,但不建議撰寫任何判斷式,這樣就失去使用Drools 的意義。

設定kmodule:

為了讓等等Java 程式可以運行Drools,我們還需要在”META-INF”資料夾下新增”kmodule.xml”並填入以下內容:

<?xml version="1.0" encoding="UTF-8"?>
<kmodule xmlns="http://www.drools.org/xsd/kmodule">
<kbase name="rules" packages="rules">
<ksession name="testdrools"/>
</kbase>
</kmodule>

撰寫入口程式:

最後我們就可以撰寫入口程式並執行測試啦,程式碼如下:

package com.test;

import com.pojo.Person;
import org.kie.api.KieServices;
import org.kie.api.runtime.KieContainer;
import org.kie.api.runtime.KieSession;

public class RuleTest {
public static void main(String[] args) {
KieServices kss = KieServices.Factory.get();
KieContainer kc = kss.getKieClasspathContainer();
KieSession ks = kc.newKieSession("testdrools");
Person person = new Person();
person.setName("kevin");
person.setAge(19);
ks.insert(person);
int count = ks.fireAllRules();
System.out.println("共執行了"+count+"條rule");
ks.dispose();
}
}

其中kc.newKieSession() 內容需對應到kmodule 裡的ksession name;物件透過ks.insert() 傳送至規則檔裡;而ks.fireAllRules() 會計算總共執行幾條規則並將數量回傳。

執行結果如下圖所示,可以看到”test.drl”規則檔確實收到新增的person 物件並執行年齡的判斷,此範例中第一、二條規則符合,而第三條規則不符合。

執行結果

後記:

本篇分享了Drools 的安裝設定流程與執行基本範例,Drools 的規則檔其實還可以有很多語法跟屬性可以使用,(要是有空的話),我再來整理分享~

至於應用於CEP的話,因為我也還沒有讀完,所以還沒有辦法分享,但這個之後應該是一定會產出一篇來介紹的!

參考資料:

來志輝 (2019)。Drools規則引擎技術指南。北京:北京大學出版社。

https://docs.drools.org/8.31.0.Final/drools-docs/docs-website/drools/introduction/index.html

非常感謝讀完本篇文章,希望本文能對你有些幫助,記得按拍手給我一些鼓勵,Medium 文章中一個人最多能按 50 下 !

--

--

邱奕修
邱奕修

No responses yet