目錄
- 一、背景
- 二、一個簡單的決策表
- 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
檔案中。
二、一個簡單的決策表

在上面這個圖中
ResultSet
和
ResultTable
是必須的,而且同一個包中,我們最好隻上傳一個決策表。
1、在同一個決策表中處理多個Sheet頁
2、RuleSet下方可以有哪些屬性
Label | Value | Usage |
---|---|---|
| The package name for the generated DRL file. Optional, the default is . | Must be the first entry. |
| or . If , then salience is used to ensure that rules fire from the top down. | Optional, at most once. If omitted, no firing order is imposed. |
| 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. |
| 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. |
| or . If , then quotation marks are escaped so that they appear literally in the DRL. | Optional, at most once. If omitted, quotation marks are escaped. |
| or . If , then the format for numeric values is ignored, for example, percent and currency. | Optional, at most once. If omitted, DRL takes formatted values. |
| A comma-separated list of Java classes to import from another package. | Optional, may be used repeatedly. |
| Declarations of DRL globals (a type followed by a variable name). Multiple global definitions must be separated by commas. | Optional, may be used repeatedly. |
| One or more function definitions, according to DRL syntax. | Optional, may be used repeatedly. |
| One or more query definitions, according to DRL syntax. | Optional, may be used repeatedly. |
| One or more declarative types, according to DRL syntax. | Optional, may be used repeatedly. |
| 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. |
| or . The dialect used in the actions of the decision table. | Optional, at most once. If omitted, is imposed. |
ResultSet
:區域隻可有一個。
3、RuleTable下方可以有哪些屬性
Label | Or custom label that begins with | Value | Usage |
---|---|---|---|
| N | Provides the name for the rule generated from that row. The default is constructed from the text following the tag and the row number. | At most one column. |
| I | Results in a comment within the generated rule. | At most one column. |
| C | Code snippet and interpolated values for constructing a constraint within a pattern in a condition. | At least one per rule table. |
| A | Code snippet and interpolated values for constructing an action for the consequence of the rule. | At least one per rule table. |
| @ | 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、項目實作結構圖
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、編寫決策表
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、測試結果
從上圖中可知,我們的規則都正常執行了。
五、完整代碼
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