天天看點

drools決策表的簡單使用

目錄

  • 一、背景
  • 二、一個簡單的決策表
    • 1、在同一個決策表中處理多個Sheet頁
    • 2、RuleSet下方可以有哪些屬性
    • 3、RuleTable下方可以有哪些屬性
    • 4、規則屬性的編寫
  • 三、需求
  • 四、實作
    • 1、項目實作結構圖
    • 2、引入jar包
    • 3、編寫kmodule.xml檔案
    • 4、編寫學生實體類
    • 5、編寫決策表
    • 6、将決策表轉換成drl檔案
      • 1、決策表轉換成drl檔案代碼
      • 2、轉換成具體的drl檔案為
    • 7、測試
      • 1、編寫測試代碼
    • 2、測試結果
  • 五、完整代碼
  • 六、參考文檔

一、背景

在之前的文章中,我們的業務規則都是寫在了

drl

檔案中,這對開發人員來說是沒有什麼問題,如果是業務人員則不怎麼友好,這篇文章我們簡單學習一下

drools

中決策表的使用,規則是寫在

excel

檔案中。

二、一個簡單的決策表

drools決策表的簡單使用

在上面這個圖中

ResultSet

ResultTable

是必須的,而且同一個包中,我們最好隻上傳一個決策表。

1、在同一個決策表中處理多個Sheet頁

drools決策表的簡單使用

2、RuleSet下方可以有哪些屬性

Label Value Usage

RuleSet

The package name for the generated DRL file. Optional, the default is

rule_table

.
Must be the first entry.

Sequential

true

or

false

. If

true

, then salience is used to ensure that rules fire from the top down.
Optional, at most once. If omitted, no firing order is imposed.

SequentialMaxPriority

Integer numeric value Optional, at most once. In sequential mode, this option is used to set the start value of the salience. If omitted, the default value is 65535.

SequentialMinPriority

Integer numeric value Optional, at most once. In sequential mode, this option is used to check if this minimum salience value is not violated. If omitted, the default value is 0.

EscapeQuotes

true

or

false

. If

true

, then quotation marks are escaped so that they appear literally in the DRL.
Optional, at most once. If omitted, quotation marks are escaped.

IgnoreNumericFormat

true

or

false

. If

true

, then the format for numeric values is ignored, for example, percent and currency.
Optional, at most once. If omitted, DRL takes formatted values.

Import

A comma-separated list of Java classes to import from another package. Optional, may be used repeatedly.

Variables

Declarations of DRL globals (a type followed by a variable name). Multiple global definitions must be separated by commas. Optional, may be used repeatedly.

Functions

One or more function definitions, according to DRL syntax. Optional, may be used repeatedly.

Queries

One or more query definitions, according to DRL syntax. Optional, may be used repeatedly.

Declare

One or more declarative types, according to DRL syntax. Optional, may be used repeatedly.

Unit

The rule units that the rules generated from this decision table belong to. Optional, at most once. If omitted, the rules do not belong to any unit.

Dialect

java

or

mvel

. The dialect used in the actions of the decision table.
Optional, at most once. If omitted,

java

is imposed.

ResultSet

:區域隻可有一個。

3、RuleTable下方可以有哪些屬性

Label Or custom label that begins with Value Usage

NAME

N Provides the name for the rule generated from that row. The default is constructed from the text following the

RuleTable

tag and the row number.
At most one column.

DESCRIPTION

I Results in a comment within the generated rule. At most one column.

CONDITION

C Code snippet and interpolated values for constructing a constraint within a pattern in a condition. At least one per rule table.

ACTION

A Code snippet and interpolated values for constructing an action for the consequence of the rule. At least one per rule table.

METADATA

@ Code snippet and interpolated values for constructing a metadata entry for the rule. Optional, any number of columns.

具體的使用可以見上方的圖

4、規則屬性的編寫

ResultSet

ResultTable

這個地方都可以編寫規則屬性。

ResultSet

地方的規則屬性将影響同一個包下所有的規則,而

ResultTable

這個地方的規則屬性,隻影響這個規則。

ResultTable

的優先級更高。

支援的規則屬性有:

PRIORITY

DATE-EFFECTIVE

DATE-EXPIRES

NO-LOOP

AGENDA-GROUP

ACTIVATION-GROUP

DURATION

TIMER

CALENDAR

AUTO-FOCUS

LOCK-ON-ACTIVE

RULEFLOW-GROUP

具體的用法:見上圖中

ACTIVATION-GROUP

的使用。

三、需求

我們需要根據學生的成績分數,給出相應的結果。規則如下:

特殊處理的規則:

規則一:隻要名字是

張三

的,

直接判定為 優

規則二:隻要名字是

李四

的,如果

分數在0,60

之間,直接認為是

一般

普通規則:

規則三:分數在

0,60

之間認為是

不及格

規則四:分數在

60,70

之間認為是

一般

規則五:分數在

70,90

之間認為是

良好

規則六:分數在

90,100

之間認為是

從上方的規則中,我們可以看到姓名為

張三

李四

的學生特殊處理了。

四、實作

1、項目實作結構圖

drools決策表的簡單使用

2、引入jar包

<dependencyManagement>
    <dependencies>
        <dependency>
            <groupId>org.drools</groupId>
            <artifactId>drools-bom</artifactId>
            <type>pom</type>
            <version>7.69.0.Final</version>
            <scope>import</scope>
        </dependency>
    </dependencies>
</dependencyManagement>

<dependencies>
    <dependency>
        <groupId>org.drools</groupId>
        <artifactId>drools-compiler</artifactId>
    </dependency>
    <dependency>
        <groupId>org.drools</groupId>
        <artifactId>drools-mvel</artifactId>
    </dependency>
    <!-- 決策表 -->
    <dependency>
        <groupId>org.drools</groupId>
        <artifactId>drools-decisiontables</artifactId>
    </dependency>
    <dependency>
        <groupId>ch.qos.logback</groupId>
        <artifactId>logback-classic</artifactId>
        <version>1.2.11</version>
    </dependency>
    <dependency>
        <groupId>org.projectlombok</groupId>
        <artifactId>lombok</artifactId>
        <version>1.18.22</version>
    </dependency>
</dependencies>
           

3、編寫kmodule.xml檔案

<kmodule xmlns="http://www.drools.org/xsd/kmodule">
    <kbase name="kabse" packages="rules.decision.tables" default="false">
        <ksession name="ksession" default="false" type="stateful"/>
    </kbase>
</kmodule>
           

4、編寫學生實體類

@Getter
@Setter
@ToString
public class Student {

    private String name;
    // 分數隻能在 0-100 之間
    private Integer score;

    public Student(String name, Integer score) {
        this.name = name;
        if (null == score || score < 0 || score > 100) {
            throw new RuntimeException("分數隻能在0-100之間");
        }
        this.score = score;
    }
}
           

5、編寫決策表

drools決策表的簡單使用

6、将決策表轉換成drl檔案

這步主要是為了檢視我們的決策表編寫的是否正确,看看最終生成的drl檔案是什麼樣的

1、決策表轉換成drl檔案代碼

/**
* 決策表轉換成 drl 檔案
*/
public static void decisionTable2Drl() throws IOException {
    Resource resource = ResourceFactory.newClassPathResource("rules/decision/tables/student-score.xlsx", "UTF-8");
    InputStream inputStream = resource.getInputStream();
    SpreadsheetCompiler compiler = new SpreadsheetCompiler();
    String drl = compiler.compile(inputStream, InputType.XLS);
    log.info("決策表轉換的drl内容為:\r{}", drl);

    // 驗證一下 drl 檔案是否有問題
    KieHelper kieHelper = new KieHelper();
    Results results = kieHelper.addContent(drl, ResourceType.DRL).verify();
    List<Message> messages = results.getMessages(Message.Level.ERROR);
    if (null != messages && !messages.isEmpty()) {
        for (Message message : messages) {
            log.error(message.getText());
        }
    }
}
           

2、轉換成具體的drl檔案為

package rules.decision.tables;
//generated from Decision Table
import java.lang.StringBuilder;
import com.huan.drools.Student;
global java.lang.StringBuilder resultsInfo;



// rule values at B15, header at B10
rule "student-score-name-1"
/* 1、姓名為張三的特殊處理
2、自定義規則的名字 */
	salience 65535
	activation-group "score"
	when
		$stu: Student(name == "張三")
	then
		resultsInfo.append("張三特殊處理:");
System.out.println("規則:" + drools.getRule().getName() + " 執行了.");
		resultsInfo.append("優");
System.out.println("規則:" + drools.getRule().getName() + " 執行了.");
end

// rule values at B16, header at B10
rule "student-score_16"
	salience 65534
	activation-group "score"
	when
		$stu: Student(name == "李四", score > 0 && score < 60)
	then
		resultsInfo.append("李四部分特殊處理:");
System.out.println("規則:" + drools.getRule().getName() + " 執行了.");
		resultsInfo.append("一般");
System.out.println("規則:" + drools.getRule().getName() + " 執行了.");
end

// rule values at B17, header at B10
rule "student-score_17"
	salience 65533
	activation-group "score"
	when
		$stu: Student(score > 0 && score < 60)
	then
		resultsInfo.append("不及格");
System.out.println("規則:" + drools.getRule().getName() + " 執行了.");
end

// rule values at B18, header at B10
rule "student-score_18"
	salience 65532
	activation-group "score"
	when
		$stu: Student(score > 60 && score < 70)
	then
		resultsInfo.append("一般");
System.out.println("規則:" + drools.getRule().getName() + " 執行了.");
end

// rule values at B19, header at B10
rule "student-score_19"
	salience 65531
	activation-group "score"
	when
		$stu: Student(score > 70 && score < 90)
	then
		resultsInfo.append("良好");
System.out.println("規則:" + drools.getRule().getName() + " 執行了.");
end

// rule values at B20, header at B10
rule "student-score_20"
	salience 65530
	activation-group "score"
	when
		$stu: Student(score > 90 && score < 100)
	then
		resultsInfo.append("優");
System.out.println("規則:" + drools.getRule().getName() + " 執行了.");
end
           

從上方可以看出

第一個規則

規則名稱

是不一樣的,而且存在一些描述資訊,這個是在決策表中特殊處理了。

7、測試

1、編寫測試代碼

package com.huan.drools;

import lombok.extern.slf4j.Slf4j;
import org.drools.decisiontable.InputType;
import org.drools.decisiontable.SpreadsheetCompiler;
import org.kie.api.KieServices;
import org.kie.api.builder.Message;
import org.kie.api.builder.Results;
import org.kie.api.io.Resource;
import org.kie.api.io.ResourceType;
import org.kie.api.runtime.KieContainer;
import org.kie.api.runtime.KieSession;
import org.kie.internal.io.ResourceFactory;
import org.kie.internal.utils.KieHelper;

import java.io.IOException;
import java.io.InputStream;
import java.util.List;

/**
 * drools 決策表的使用
 */
@Slf4j
public class DroolsDecisionTableApplication {
    public static void main(String[] args) throws IOException {
        decisionTable2Drl();
        KieServices kieServices = KieServices.get();
        KieContainer kieContainer = kieServices.newKieClasspathContainer();
        // 張三雖然隻得20分,但是根據規則判斷,結果應該是  優
        invokedDecisionTable(kieContainer, new Student("張三", 20));
        // 李四雖然隻得20分,但是根據規則判斷,結果應該是  一般
        invokedDecisionTable(kieContainer, new Student("李四", 20));
        // 李四得75分,但是根據規則判斷,結果應該是  良好
        invokedDecisionTable(kieContainer, new Student("李四", 75));
        // 王五得59分,但是根據規則判斷,結果應該是  不及格
        invokedDecisionTable(kieContainer, new Student("王五", 59));
        // 趙六得20分,但是根據規則判斷,結果應該是  一般
        invokedDecisionTable(kieContainer, new Student("趙六", 65));
        // 錢七得20分,但是根據規則判斷,結果應該是  良好
        invokedDecisionTable(kieContainer, new Student("錢七", 75));
        // 李八得20分,但是根據規則判斷,結果應該是  優
        invokedDecisionTable(kieContainer, new Student("李八", 95));
    }

    public static void invokedDecisionTable(KieContainer kieContainer, Student student) {
        System.out.println("\r");
        KieSession kieSession = kieContainer.newKieSession("ksession");
        StringBuilder result = new StringBuilder();
        kieSession.setGlobal("resultsInfo", result);
        kieSession.insert(student);
        kieSession.fireAllRules();
        kieSession.dispose();
        System.out.println("規則執行結果:" + result);
    }

    /**
     * 決策表轉換成 drl 檔案
     */
    public static void decisionTable2Drl() throws IOException {
        Resource resource = ResourceFactory.newClassPathResource("rules/decision/tables/student-score.xlsx", "UTF-8");
        InputStream inputStream = resource.getInputStream();
        SpreadsheetCompiler compiler = new SpreadsheetCompiler();
        String drl = compiler.compile(inputStream, InputType.XLS);
        log.info("決策表轉換的drl内容為:\r{}", drl);
        // 驗證一下 drl 檔案是否有問題
        KieHelper kieHelper = new KieHelper();
        Results results = kieHelper.addContent(drl, ResourceType.DRL).verify();
        List<Message> messages = results.getMessages(Message.Level.ERROR);
        if (null != messages && !messages.isEmpty()) {
            for (Message message : messages) {
                log.error(message.getText());
            }
        }
    }
}
           

2、測試結果

drools決策表的簡單使用

從上圖中可知,我們的規則都正常執行了。

五、完整代碼

https://gitee.com/huan1993/spring-cloud-parent/tree/master/drools/drools-decision-table

六、參考文檔

1、https://docs.drools.org/7.69.0.Final/drools-docs/html_single/index.html#decision-tables-con_decision-tables

本文來自部落格園,作者:huan1993,轉載請注明原文連結:https://www.cnblogs.com/huan1993/p/16325590.html