drools决策表的简单使用-
- 一、背景
-
二、一个简单的决策表
- 1、在同一个决策表中处理多个Sheet页
- 2、RuleSet下方可以有哪些属性
- 3、RuleTable下方可以有哪些属性
- 4、规则属性的编写
- 三、需求
-
四、实现
- 1、项目实现结构图
- 2、引入jar包
- 3、编写域名文件
- 4、编写学生实体类
- 5、编写决策表
-
6、将决策表转换成drl文件
- 1、决策表转换成drl文件代码
- 2、转换成具体的drl文件为
-
7、测试
- 1、编写测试代码
- 2、测试结果
- 五、完整代码
- 六、参考文档
一、背景
在之前的文章中,我们的业务规则都是写在了drl
文件中,这对开发人员来说是没有什么问题,如果是业务人员则不怎么友好,这篇文章我们简单学习一下drools
中决策表的使用,规则是写在excel
文件中。
二、一个简单的决策表
在上面这个图中ResultSet
和ResultTable
是必须的,而且同一个包中,我们最好只上传一个决策表。
1、在同一个决策表中处理多个Sheet页
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、项目实现结构图
2、引入jar包
<dependencyManagement>
<dependencies>
<dependency>
<groupId>域名ls</groupId>
<artifactId>drools-bom</artifactId>
<type>pom</type>
<version>7.域名l</version>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<dependency>
<groupId>域名ls</groupId>
<artifactId>drools-compiler</artifactId>
</dependency>
<dependency>
<groupId>域名ls</groupId>
<artifactId>drools-mvel</artifactId>
</dependency>
<!-- 决策表 -->
<dependency>
<groupId>域名ls</groupId>
<artifactId>drools-decisiontables</artifactId>
</dependency>
<dependency>
<groupId>域名ack</groupId>
<artifactId>logback-classic</artifactId>
<version>域名</version>
</dependency>
<dependency>
<groupId>域名ectlombok</groupId>
<artifactId>lombok</artifactId>
<version>域名</version>
</dependency>
</dependencies>
3、编写域名文件
<kmodule xmlns="http://域名/xsd/kmodule">
<kbase name="kabse" packages="域名es" 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) {
域名 = name;
if (null == score || score < 0 || score > 100) {
throw new RuntimeException("分数只能在0-100之间");
}
域名e = score;
}
}
5、编写决策表
6、将决策表转换成drl文件
这步主要是为了查看我们的决策表编写的是否正确,看看最终生成的drl文件是什么样的
。
1、决策表转换成drl文件代码
/**
* 决策表转换成 drl 文件
*/
public static void decisionTable2Drl() throws IOException {
Resource resource = 域名lassPathResource("rules/decision/tables/student-域名", "UTF-8");
InputStream inputStream = 域名nputStream();
SpreadsheetCompiler compiler = new SpreadsheetCompiler();
String drl = 域名ile(inputStream, 域名);
域名("决策表转换的drl内容为:\r{}", drl);
// 验证一下 drl 文件是否有问题
KieHelper kieHelper = new KieHelper();
Results results = 域名ontent(drl, 域名).verify();
List<Message> messages = 域名essages(域名R);
if (null != messages && !域名pty()) {
for (Message message : messages) {
域名r(域名ext());
}
}
}
2、转换成具体的drl文件为
package 域名es;
//generated from Decision Table
import 域名ngBuilder;
import 域名域名ent;
global 域名ngBuilder 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
域名nd("张三特殊处理:");
域名tln("规则:" + 域名ule().getName() + " 执行了.");
域名nd("优");
域名tln("规则:" + 域名ule().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
域名nd("李四部分特殊处理:");
域名tln("规则:" + 域名ule().getName() + " 执行了.");
域名nd("一般");
域名tln("规则:" + 域名ule().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
域名nd("不及格");
域名tln("规则:" + 域名ule().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
域名nd("一般");
域名tln("规则:" + 域名ule().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
域名nd("良好");
域名tln("规则:" + 域名ule().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
域名nd("优");
域名tln("规则:" + 域名ule().getName() + " 执行了.");
end
从上方可以看出第一个规则
的规则名称
是不一样的,而且存在一些描述信息,这个是在决策表中特殊处理了。
7、测试
1、编写测试代码
package 域名ls;
import 域名域名j;
import 域名域名tType;
import 域名域名adsheetCompiler;
import 域名.KieServices;
import 域名.域名age;
import 域名.域名lts;
import 域名.域名urce;
import 域名.域名urceType;
import 域名.域名ontainer;
import 域名.域名ession;
import 域名域名urceFactory;
import 域名域名elper;
import 域名ception;
import 域名tStream;
import 域名;
/**
* drools 决策表的使用
*/
@Slf4j
public class DroolsDecisionTableApplication {
public static void main(String[] args) throws IOException {
decisionTable2Drl();
KieServices kieServices = 域名();
KieContainer kieContainer = 域名ieClasspathContainer();
// 张三虽然只得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) {
域名tln("\r");
KieSession kieSession = 域名ieSession("ksession");
StringBuilder result = new StringBuilder();
域名lobal("resultsInfo", result);
域名rt(student);
域名AllRules();
域名ose();
域名tln("规则执行结果:" + result);
}
/**
* 决策表转换成 drl 文件
*/
public static void decisionTable2Drl() throws IOException {
Resource resource = 域名lassPathResource("rules/decision/tables/student-域名", "UTF-8");
InputStream inputStream = 域名nputStream();
SpreadsheetCompiler compiler = new SpreadsheetCompiler();
String drl = 域名ile(inputStream, 域名);
域名("决策表转换的drl内容为:\r{}", drl);
// 验证一下 drl 文件是否有问题
KieHelper kieHelper = new KieHelper();
Results results = 域名ontent(drl, 域名).verify();
List<Message> messages = 域名essages(域名R);
if (null != messages && !域名pty()) {
for (Message message : messages) {
域名r(域名ext());
}
}
}
}
2、测试结果
从上图中可知,我们的规则都正常执行了。
五、完整代码
https://域名/huan1993/spring-cloud-parent/tree/master/drools/drools-decision-table
六、参考文档
1、https://域名/7.域名l/drools-docs/html_single/域名#decision-tables-con_decision-tables