Drools 規則引擎環境搭建
一、關於 drools 規則引擎
前面寫過一篇 Drools 規則引擎相關的文章,這篇文章主要記錄一下規則引擎的環境搭建和簡單示例。不熟悉 drools 的朋友可以看看這篇文章: 自己寫個 Drools 檔案語法檢查工具——棧的應用之編譯器檢測語法錯誤
介紹的內容:
- Drools 規則引擎的使用場景
- Drools 規則引擎的優點
- Drools的基本工作工程(Fact物件、Drl檔案內容、Drools的基礎語法)
- drools 檔案的形式
- Drools 檔案語法初步檢查
二 、Drools 的環境搭建及簡單示例
環境: idea + jdk1.8 + gradle
我用的是 gradle 構建 java 工程的方式、用 maven 構建的可以參考配置
構造這樣一個需求背景,雙十一來了,商品打折,假設商品價格 (0,500], 打85折,商品價格 (500, 1000],打8折, 商品價格 (1000,∞), 一律減 300。
1. 建立專案
新建一個 gradle 專案,建立包:com.sharpcj
,新建類 Product.java
和 Main.java
:
Product.java
檔案如下:
package com.sharpcj; public class Product { private String name; // 商品名稱 private double prePrice; // 商品定價 private double realPrice; //商品實際售價 public Product() { } public Product(String name, double prePrice) { this.name = name; this.prePrice = prePrice; } public String getName() { return name; } public void setName(String name) { this.name = name; } public double getPrePrice() { return prePrice; } public void setPrePrice(double prePrice) { this.prePrice = prePrice; } public double getRealPrice() { return realPrice; } public void setRealPrice(double realPrice) { this.realPrice = realPrice; } }
然後在 Main.java
新建 main 方法。
2. Gradle引入Drools庫
開啟 build.gradle
檔案,新增相應的外掛和依賴
plugins { id 'java' } plugins { id 'application' } mainClassName = 'com.sharpcj.Main' group 'com.sharpcj' version '1.0-SNAPSHOT' sourceCompatibility = 1.8 repositories { mavenCentral() } dependencies { testCompile group: 'junit', name: 'junit', version: '4.12' compile group: 'org.kie', name: 'kie-api', version: '7.5.0.Final' compile group: 'org.drools', name: 'drools-compiler', version: '7.5.0.Final' }
引入 Java 外掛,使Gradle可以構建Java程式碼,同時引入了執行Drools依賴的兩個庫, 指定了 mainClassName
。
3.編寫 drools 檔案
在 resources
目錄下面新建包 demo.rules
,用來存放 drools 規則檔案。然後新建檔案 product.drl
,
內容如下:
package com.sharpcj;
rule "Product price less than 500" // 給規則取個名
when
pp : Product( prePrice <= 500 ) // 規則
then
// 符合規則後執行的操作,是Java程式碼
double prePrice = pp.getPrePrice();
pp.setRealPrice(prePrice * 0.85);
System.out.println(pp.getName() + "活動價是:" + pp.getRealPrice());
end
rule "Product price less than 1000" // 給規則取個名
when
p : Product( prePrice > 500 && prePrice <=1000 ) // 規則
then
// 符合規則後執行的操作,是Java程式碼
double prePrice = p.getPrePrice();
p.setRealPrice(prePrice * 0.8);
System.out.println(p.getName() + "活動價是:" + p.getRealPrice());
end
rule "Product price more than 1000" // 給規則取個名
when
p : Product( prePrice > 1000 ) // 規則
then
// 符合規則後執行的操作,是Java程式碼
double prePrice = p.getPrePrice();
p.setRealPrice(prePrice - 300);
System.out.println(p.getName() + "活動價是:" + p.getRealPrice());
end
4.編寫配置檔案
執行 drools 需要一個固定的配置檔案,在 resources
檔案下的目錄 META_INF
,名稱固定為 kmodule.xml
:
配置檔案至少包含如下幾行:
<kmodule xmlns="http://www.drools.org/xsd/kmodule">
<kbase name="kbase1" packages="demo.rules">
<ksession name="ksession1" />
</kbase>
</kmodule>
配置簡單說明:
- Kmodule中可以包含一個到多個kbase,分別對應drl的規則檔案。
- Kbase需要一個唯一的name,可以取任意字串。
- packages為drl檔案所在resource目錄下的路徑。注意區分drl檔案中的package與此處的package不一定相同。
- 多個包用逗號分隔。預設情況下會掃描resources目錄下所有(包含子目錄)規則檔案。
- kbase的default屬性,標示當前KieBase是不是預設的,如果是預設的則不用名稱就可以查詢到該KieBase,但每個module最多隻能有一個預設KieBase。
- kbase下面可以有一個或多個ksession,ksession的name屬性必須設定,且必須唯一。
5.讓規則檔案程式跑起來
在 Main.java
類中編寫測試方法,讓規則檔案跑起來:
package com.sharpcj;
import org.kie.api.KieServices;
import org.kie.api.runtime.KieContainer;
import org.kie.api.runtime.KieSession;
public class Main {
public static void main(String[] args){
new Main().test();
}
private void test(){
// 構建KieServices
KieServices ks = KieServices.Factory.get();
KieContainer kc = ks.getKieClasspathContainer();
// 獲取kmodule.xml中配置中名稱為ksession-rule的session,預設為有狀態的。
KieSession kSession = kc.newKieSession("ksession1");
Product fan = new Product("電扇", 280);
Product washer = new Product("洗衣機",2200);
Product phone = new Product("手機", 998);
kSession.insert(fan);
kSession.insert(washer);
kSession.insert(phone);
kSession.fireAllRules();
kSession.dispose();
}
}
執行結果:
三、其它說明
1.不使用配置檔案形式
上面使用的配置檔案形式載入 drools 檔案是 drools 7.x 版本才有的,在此之前,我們通常使用程式碼形式載入規則檔案,當然在 drools 7.x 中依然可以使用這種方式,只不過有些 API 已經過時了,或者更新了。下面用程式碼形式載入規則檔案程式碼如下:
/**
* 不使用 drools 7.x 配置檔案
*/
private void test2(){
KnowledgeBuilder kbuilder = KnowledgeBuilderFactory.newKnowledgeBuilder();
kbuilder.add(ResourceFactory.newClassPathResource("demo/rules/product.drl"), ResourceType.DRL);
KnowledgeBuilderErrors errors = kbuilder.getErrors();
if (errors.size() > 0) {
for (KnowledgeBuilderError error: errors) {
System.err.println(error);
}
throw new IllegalArgumentException("Could not parse knowledge.");
}
// 註釋掉的是 drools 6.x API
/*KnowledgeBase kbase = KnowledgeBaseFactory.newKnowledgeBase();
kbase.addKnowledgePackages(kbuilder.getKnowledgePackages());
StatefulKnowledgeSession ksession = kbase.newStatefulKnowledgeSession();*/
// drools 7.x API
InternalKnowledgeBase kbase = KnowledgeBaseFactory.newKnowledgeBase();
Collection<KiePackage> pkgs = kbuilder.getKnowledgePackages();
kbase.addPackages(pkgs);
KieSession kieSession = kbase.newKieSession();
Product fan = new Product("電扇", 280);
Product washer = new Product("洗衣機",2200);
Product phone = new Product("手機", 998);
kieSession.insert(fan);
kieSession.insert(washer);
kieSession.insert(phone);
kieSession.fireAllRules();
kieSession.dispose();
}
執行程式依然能得到相同的結果。
2.規則檔案的型別
規則檔案除了 drl 檔案之類,還有其它型別的檔案,如 xls, csv。
四、附錄
Drools 官網首頁: https://www.drools.org/
Drools 官方文件: https://docs.jboss.org/drools/release/7.12.0.Final/drools-docs/html_single/index.html