Drools簡單入門

因爲在項目要用到Drools,所以下面寫了一個簡單的例子學習入門。

一、Drools簡介:

JBoss Rules 的前身是Codehaus的一個開源項目叫 Drools。最近被納入JBoss門下,更名爲JBoss Rules,成爲了JBoss應用服務器的規則引擎。

Drools 是爲 Java 量身定製的基於Charles Forgy的RETE算法的規則引擎的實現。具有了OO接口的RETE,使得商業規則有了更自然的表達。

Drools 的用 XML 的<Conditons>、<Consequence> 節點表達If–Then句式,而裏面可以嵌入上述語言的代碼作爲判斷語句和執行語句。

其中 Java 代碼會使用Antlr進行解釋,而 Groovy 和 Python 本身就是腳本語言,可以直接調用。

Drools 的聰明之處在於,用 XML 節點來規範 If–Then 句式和事實的定義,使引擎幹起活來很舒服。

而使用 Java,Groovy等原生語言來做判斷和執行語句,讓程序員很容易過渡、移植,學習曲線很低。

二、幾個重要概念

  • 事實(Fact):對象之間及對象屬性之間的關係
  • 規則(rule):是由條件和結論構成的推理語句,一般表示爲if...Then。一個規則的if部分稱爲LHS,then部分稱爲RHS。
  • 模式(module):就是指IF語句的條件。這裏IF條件可能是有幾個更小的條件組成的大條件。模式就是指的不能在繼續分割下去的最小的原子條件。

三、.drl 文件內容

package com.rules

import com.drools.model.Person
import com.drools.model.Goods

rule "test-drools-older than 60"

when
     no-loop true
     lock-on-active true
     salience 1
     $Goods : Goods(person.age > 60)
then
     $Goods.setDiscount(80);
     System.out.println("test-drools-older than 60 " + $Goods.getPerson().getAge());
end
  • package 與Java語言類似,drl的頭部需要有package和import的聲明,package不必和物理路徑一致。
  • import 導出java Bean的完整路徑,也可以將Java靜態方法導入調用。
  • rule 規則名稱,需要保持唯一 件,可以無限次執行。
  • no-loop 定義當前的規則是否不允許多次循環執行,默認是 false,也就是當前的規則只要滿足條件,可以無限次執行。
  • lock-on-active 將lock-on-active屬性的值設置爲true,可避免因某些Fact對象被修改而使已經執行過的規則再次被激活執行。
  • salience 用來設置規則執行的優先級,salience 屬性的值是一個數字,數字越大執行優先級越高, 同時它的值可以是一個負數。默認情況下,規則的 salience 默認值爲 0。如果不設置規則的 salience 屬性,那麼執行順序是隨機的。
  • when 條件語句,就是當到達什麼條件的時候
  • then 根據條件的結果,來執行什麼動作
  • end 規則結束

這個規則文件就是描述了,當符合什麼條件的時候,應該去做什麼事情,每當規則有變動的時候,我們只需要修改規則文件,然後重新加載即可生效。

四、kmodule.xml

kmodule.xml的作用就是告訴代碼規則文件drl在哪裏,在drools中這個文件就是kmodule.xml,放置到resources/META-INF目錄下。kmodule.xml內容如下:

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

以下對配置說明進行簡單說明:

  • Kmodule 中可以包含一個到多個 kbase,分別對應 drl 的規則文件。
  • Kbase 需要一個唯一的 name,可以取任意字符串。
  • packages 爲drl文件所在resource目錄下的路徑。注意區分drl文件中的package與此處的package不一定相同。多個包用逗號分隔。默認情況下會掃描 resources目錄下所有(包含子目錄)規則文件。
  • kbase的default屬性,標示當前KieBase是不是默認的,如果是默認的則不用名稱
    就可以查找到該 KieBase,但每個 module 最多只能有一個默認 KieBase。
  • kbase 下面可以有一個或多個 ksession,ksession 的 name 屬性必須設置,且必須唯一。

五、下面是一個簡單的入門例子

1、首先項目的結構如下

2、引入drools的依賴

    <dependencies>
        <dependency>
            <groupId>org.drools</groupId>
            <artifactId>drools-core</artifactId>
            <version>7.7.0.Final</version>
        </dependency>
        <dependency>
            <groupId>org.drools</groupId>
            <artifactId>drools-compiler</artifactId>
            <version>7.7.0.Final</version>
        </dependency>
        <dependency>
            <groupId>org.drools</groupId>
            <artifactId>drools-templates</artifactId>
            <version>7.7.0.Final</version>
        </dependency>
    </dependencies>

3、創建一個xml,注意一定要放在META-INF文件夾下,drools會自動解析它

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

4、創建實體Goods和Person

5、創建規則droolsRules.drl

package com.rules

import com.drools.model.Person
import com.drools.model.Goods

rule "test-drools-older than 60"

when
     $Goods : Goods(person.age > 60)
then
     $Goods.setDiscount(80);
     System.out.println("test-drools-older than 60 " + $Goods.getPerson().getAge());
 end

 rule "test-drools-other"
 when
     $Goods : Goods(person.age <= 60)
 then
     $Goods.setDiscount(70);
     System.out.println("test-drools-other " + $Goods.getPerson().getAge());
 end

6、測試類

public class DroolsTest {

    public static void main(String[] args) {
        //獲取一個實例
        KieServices kieServices = KieServices.Factory.get();
        //默認去讀取配置文件
        KieContainer kieContainer = kieServices.getKieClasspathContainer();
        //根據這個名詞去獲取kieSession
        KieSession kieSession = kieContainer.newKieSession("all-rules");

        Person p1 = new Person();
        p1.setAge(30);
        p1.setName("Tom");
        Goods g1 = new Goods();
        g1.setPerson(p1);

        Person p2 = new Person();
        p2.setAge(70);
        p2.setName("Joy");
        Goods g2 = new Goods();
        g2.setPerson(p2);

        //將person實例放入session中
        kieSession.insert(g1);
        kieSession.insert(g2);

        //開始執行規則,並獲取執行了多少條規則
        int count = kieSession.fireAllRules();
        //關閉session
        kieSession.dispose();
        System.out.println("Fire " + count + " rule(s)!");
        System.out.println("The discount of g1 is " + g1.getDiscount() + "%");
        System.out.println("The discount of g2 is " + g2.getDiscount() + "%");

    }
}

7、運行結果

test-drools-older than 60 70
test-drools-other 30
Fire 2 rule(s)!
The discount of g1 is 70%
The discount of g2 is 80%

參考:Drools 規則文件語法概述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章