天天看點

【Drools一】值得打勞工學習的規則引擎Drools規則引擎Drools介紹構成實戰

本文主要對Drools的使用業務場景做簡單介紹。

規則引擎

規則引擎:全稱為業務規則管理系統,英文名為BRMS(即Business Rule Management System)。規則引擎的主要思想是将應用程式中的業務決策部分分離出來,并使用預定義的語義子產品編寫業務決策(業務規則),由使用者或開發者在需要時進行配置、管理。

需要注意的是規則引擎并不是一個具體的技術架構,而是指的一類系統,即業務規則管理系統。

目前市面上具體的規則引擎産品有:drools、VisualRules、iLog等。

規則引擎實作了将業務決策從應用程式代碼中分離出來,接收資料輸入,解釋業務規則,并根據業務規則做出業務決策。規則引擎其實就是一個輸入輸出平台。

Drools介紹

drools是一款由JBoss組織提供的基于Java語言開發的開源規則引擎,可以将複雜且多變的業務規則從寫死中解放出來,以規則腳本的形式存放在檔案或特定的存儲媒體中(例如存放在資料庫中),使得業務規則的變更不需要修改項目代碼、不用重新開機伺服器就可以線上上環境立即生效。

drools官網位址

:https://drools.org/

drools源碼下載下傳位址

:https://github.com/kiegroup/drools

  • 使用規則引擎能夠解決什麼問題?

    針對複雜的業務規則代碼處理,往往存在一下問題:

    1、寫死實作業務規則難以維護;

    2、寫死實作業務規則難以應對變化;

    3、業務規則發生變化需要修改代碼,重新開機服務後才能生效;

    于是規則引擎Drools便誕生在項目中。。。

  • 使用規則引擎的優勢如下:

    1、業務規則與系統代碼分離,實作業務規則的集中管理

    2、在不重新開機服務的情況下可随時對業務規則進行擴充和維護

    3、可以動态修改業務規則,進而快速響應需求變更

    4、規則引擎是相對獨立的,隻關心業務規則,使得業務分析人員也可以參與編輯、維護系統的業務規則

    5、減少了寫死業務規則的成本和風險

    6、使用規則引擎提供的規則編輯工具,使複雜的業務規則實作變得的簡單

構成

drools規則引擎由以下三部分構成:

  • Working Memory

    :工作記憶體,drools規則引擎會從Working Memory中擷取資料并和規則檔案中定義的規則進行模式比對,是以我們開發的應用程式隻需要将我們的資料插入到Working Memory中即可;
  • Rule Base

    :規則庫,我們在規則檔案中定義的

    規則

    都會被加載到規則庫中
  • Inference Engine

    :推理引擎

    其中Inference Engine(推理引擎)又包括:

  1. Pattern Matcher(比對器): 具體比對哪一個規則,由這個完成,将Rule Base中的所有規則與Working Memory中的Fact對象進行模式比對,比對成功的規則将被激活并放入Agenda中。
  2. Agenda(議程):用于存放通過比對器進行模式比對後被激活的規則。
  3. Execution Engine(執行引擎):執行Agenda中被激活的規則。
Fact:事實,是指在drools 規則應用當中,**将一個普通的JavaBean插入到Working Memory後的對象就是Fact對象**,Fact對象是我們的應用和規則引擎進行資料互動的橋梁或通道。
           

規則引擎執行過程

【Drools一】值得打勞工學習的規則引擎Drools規則引擎Drools介紹構成實戰
  • 規則引擎應用場景

    對于一些存在比較複雜的業務規則并且業務規則會頻繁變動的系統比較适合使用規則引擎,如下:

    1、風險控制系統----風險貸款、風險評估

    2、反欺詐項目----銀行貸款、征信驗證

    3、決策平台系統----财務計算

    4、促銷平台系統----滿減、打折、加價購

實戰

目錄結構:

【Drools一】值得打勞工學習的規則引擎Drools規則引擎Drools介紹構成實戰
  • pom.xml中引入依賴drools
注意這裡在properties标簽中設定版本
 <properties>
        <java.version>1.8</java.version>
        <drools.version>7.28.0.Final</drools.version>
    </properties>

        <!-- start drools -->
        <dependency>
            <groupId>org.drools</groupId>
            <artifactId>drools-core</artifactId>
            <version>${drools.version}</version>
        </dependency>

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

        <dependency>
            <groupId>org.kie</groupId>
            <artifactId>kie-spring</artifactId>
            <version>${drools.version}</version>
        </dependency>

        <dependency>
            <groupId>org.kie</groupId>
            <artifactId>kie-internal</artifactId>
            <version>${drools.version}</version>
        </dependency>

        <dependency>
            <groupId>org.drools</groupId>
            <artifactId>drools-templates</artifactId>
            <version>${drools.version}</version>
        </dependency>

        <dependency>
            <groupId>org.drools</groupId>
            <artifactId>drools-decisiontables</artifactId>
            <version>7.35.0.Final</version>
        </dependency>
        <!--  end drools   -->

           
  • src/main/resources/META-INF

    目錄下建立檔案

    kmodule.xml

<?xml version="1.0" encoding="UTF-8"?>
<kmodule xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xmlns="http://www.drools.org/xsd/kmodule">
    <!--
       可以存在多個<kbase>标簽;
       name屬性值可以随意設定;
       packages:對應*.drl檔案的resources路徑

       ksession标簽必須設定;一個或者多個标簽,name屬性值唯一

       -->
    <kbase name="test-rulesKB" packages="rules">
        <ksession name="test-rulesKS"/>
    </kbase>

</kmodule>
           
  • 在src/main/resources/rules目錄下建立

    test.drl

    檔案
package rules
import com.qxy.drools.Customer

rule "customerAge"
no-loop true // 定義目前的規則是否 不允許多次循環執行,預設是 false,也就是目前的規則隻要滿足條件,可以無限次執行
lock-on-active true //将lock-on-active屬性的值設定為true,可避免因某些Fact對象被修改而使已經執行過的規則再次被激活執行。
salience 1
when
$customer:Customer(age < 10)
then
$customer.setAge($customer.getAge() + 1);
update($customer)
System.out.println($customer.getName() + ",age:" + $customer.getAge());
end
           
  • 運作測試
import org.kie.api.KieServices;
import org.kie.api.runtime.KieContainer;
import org.kie.api.runtime.KieSession;

/**
 * @author qxy
 * @date 2020/11/11 11:31 上午
 */
public class DroolTest {
    public static void main(String[] args) {
        KieServices ks = KieServices.Factory.get();
        KieContainer kc = ks.getKieClasspathContainer();
        KieSession ksession = kc.newKieSession("test-rulesKS");
        Customer customer1 = new Customer();
        customer1.setAge(1);
        customer1.setName("李三");
        Customer customer2 = new Customer();
        customer2.setAge(18);
        customer2.setName("李四");

        ksession.insert(customer1);
        ksession.insert(customer2);
        ksession.fireAllRules();
        ksession.dispose();
    }
 }