乐趣区

关于java:drools决策表的简单使用

一、背景

在之前的文章中,咱们的业务规定都是写在了 drl 文件中,这对开发人员来说是没有什么问题,如果是业务人员则不怎么敌对,这篇文章咱们简略学习一下 drools 中决策表的应用,规定是写在 excel 文件中。

二、一个简略的决策表

在下面这个图中 ResultSetResultTable是必须的,而且同一个包中,咱们最好只上传一个决策表。

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、规定属性的编写

ResultSetResultTable这个中央都能够编写规定属性。ResultSet中央的规定属性将影响同一个包下所有的规定,而 ResultTable 这个中央的规定属性,只影响这个规定。ResultTable的优先级更高。

反对的规定属性有:PRIORITYDATE-EFFECTIVEDATE-EXPIRESNO-LOOPAGENDA-GROUPACTIVATION-GROUPDURATIONTIMERCALENDARAUTO-FOCUSLOCK-ON-ACTIVERULEFLOW-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

退出移动版