一、Drools规则引擎
Drools官网:
https://www.drools.org/
Drools中文网:
http://www.drools.org.cn/
bilibili学习视频:
https://www.bilibili.com/video/BV1q34y1X77H?p=1
maven依赖:
https://mvnrepository.com/search?q=drools
gitee项目笔记:
https://gitee.com/happy_sad/drools
一、00_droolsDemo
1、pom.xml
引入依赖
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.drools</groupId>
<artifactId>drools-compiler</artifactId>
<version>7.6.0.Final</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.kie</groupId>
<artifactId>kie-api</artifactId>
<version>7.6.0.Final</version>
<scope>test</scope>
</dependency>
</dependencies>
2、Order.java
编写实体类(com.jin.rules.entity.Order.java)
package com.jin.rules.entity;
import lombok.Data;
@Data
public class Order {
/**
* 订单金额
*/
private int amount;
/**
* 积分
*/
private int score;
@Override
public String toString() {
return "Order{" +
"amount=" + amount +
", score=" + score +
'}';
}
}
3、META-INF.kmodule.xml
编写配置文件(resources.META-INF.kmodule.xml)
<?xml version="1.0" encoding="UTF-8"?>
<kmodule xmlns="http://jboss.org/kie/6.0.0/kmodule">
<!--
name:指定kbase的名称,可以任意,但是必须唯一
packages:指定规则文件的目录,需要根据实际情况填写,否则无法加载到规则文件
default:指定当前kbase是否为默认
-->
<kbase name="SimpleRuleKBase" packages="rules">
<!--
name:指定ksession的名称,可以任意,但是必须唯一
default:指定当前ksession是否为默认
-->
<ksession name="simpleRuleKSession"/>
</kbase>
</kmodule>
4、rules.score-rules.drl
编写规则文件(resources.rules.score-rules.drl)
package rules;
import com.jin.rules.entity.Order;
//100元以下不加分
rule "score_1" //名称需唯一
when
//工作内存中必须存在Order这种类型的Fact对象 ---类型约束
//Fact对象的amount属性值必须小于等于100 ---属性约束
$sssss:Order(amount < 100);
then
$sssss.setScore(0);
System.out.println("触发规则,100元以下不加分");
end
//100元-500元 加100分
rule "score_2"
when
$order:Order(100 <= amount && amount<= 500)
then
$order.setScore(100);
System.out.println("触发规则,100元-500元 加100分");
end
//500元-1000元 加500分
rule "score_3"
when
$order:Order(500 < amount && amount <= 1000)
then
$order.setScore(500);
System.out.println("触发规则,500元-1000元 加500分");
end
//1000元以上 加1000分
rule "score_4"
when
$order:Order(1000 < amount)
then
$order.setScore(1000);
System.out.println("触发规则,500元-1000元 加500分");
end
//直接触发规则
rule "score_5"
when
then
System.out.println("触发规则,LHS始终为空,规则始终触发!");
end
//enabled false
rule "score_6"
enabled false
when
then
System.out.println("触发规则!");
end
5、ApplicationTests.java
编写测试类(com.jin.rules.ApplicationTests)
package com.jin.rules;
import com.jin.rules.entity.Order;
import org.junit.jupiter.api.Test;
import org.kie.api.KieServices;
import org.kie.api.runtime.KieContainer;
import org.kie.api.runtime.KieSession;
import org.springframework.boot.test.context.SpringBootTest;
@SpringBootTest
class ApplicationTests {
@Test
void contextLoads() {
}
@Test
public void test() {
System.out.println("规则执行开始,执行规则");
//第一步 获取KieServices
KieServices kieServices = KieServices.Factory.get();
//第二步获取kieContainer
KieContainer kieClasspathContainer = kieServices.getKieClasspathContainer("SimpleRuleKBase");
//第三步获取kieSession
KieSession simpleRuleKSession = kieClasspathContainer.newKieSession("simpleRuleKSession");
//新建事实对象
Order order = new Order();
order.setAmount(235);
//第四步 插入事实对象到session中
simpleRuleKSession.insert(order);
//第五步 执行规则引擎
simpleRuleKSession.fireAllRules();
//第六步 关闭规则引擎
simpleRuleKSession.dispose();
System.out.println("规则执行完成,关闭规则");
}
}
6、测试结果
二、01_droolsDemo
1、pom.xml
引入依赖
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.drools</groupId>
<artifactId>drools-compiler</artifactId>
<version>7.6.0.Final</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.kie</groupId>
<artifactId>kie-api</artifactId>
<version>7.6.0.Final</version>
<scope>test</scope>
</dependency>
</dependencies>
2、entity实体
2.1 Customer.java
package com.jin.rules.entity;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.util.List;
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Customer {
private String name;
private List<Order> orderList;
}
2.2 Order.java
package com.jin.rules.entity;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Order {
/**
* 订单金额
*/
private int amount;
/**
* 积分
*/
private int score;
}
3、META-INF.kmodule.xml
编写配置文件(resources.META-INF.kmodule.xml)
<?xml version="1.0" encoding="UTF-8"?>
<kmodule xmlns="http://www.drools.org/xsd/kmodule">
<!--
name:指定kbase的名称,可以任意,但是必须唯一
packages:指定规则文件的目录,需要根据实际情况填写,否则无法加载到规则文件
default:指定当前kbase是否为默认
-->
<kbase name="myKbase1" packages="rules" default="true">
<!--
name:指定ksession的名称,可以任意,但是必须唯一
default:指定当前ksession是否为默认
-->
<ksession name="ksession-rule" default="true"/>
</kbase>
</kmodule>
4、rules规则文件
4.1 customer-rules.drl
package rules;
import com.jin.rules.entity.*;
//测试contains
rule "rule_1"
when
$order:Order();
$customer:Customer(orderList contains $order);
then
System.out.println("触发规则:orderList 包含$order...");
end
//测试not contains
rule "rule_2"
when
$order:Order();
$customer:Customer(orderList not contains $order);
then
System.out.println("触发规则:orderList 不包含$order...");
end
//测试比较操作符matches
rule "rule_3"
when
Customer(name matches "张.*");
then
System.out.println("触发规则:name是以张为开头的...");
end
//测试比较操作符not matches
rule "rule_4"
when
Customer(name not matches "张.*");
then
System.out.println("触发规则:name不是以张为开头的...");
end
4.2 score-rules.drl
package rules;
import com.jin.rules.entity.Order;
//100元以下不加分
rule "score_1" //名称需唯一
when
//工作内存中必须存在Order这种类型的Fact对象 ---类型约束
//Fact对象的amount属性值必须小于等于100 ---属性约束
$sssss:Order(amount < 100);
then
$sssss.setScore(0);
System.out.println("触发规则,100元以下不加分");
end
//100元-500元 加100分
rule "score_2"
when
$order:Order(100 <= amount && amount<= 500)
then
$order.setScore(100);
System.out.println("触发规则,100元-500元 加100分");
end
//500元-1000元 加500分
rule "score_3"
when
$order:Order(500 < amount && amount <= 1000)
then
$order.setScore(500);
System.out.println("触发规则,500元-1000元 加500分");
end
//1000元以上 加1000分
rule "score_4"
when
$order:Order(1000 < amount)
then
$order.setScore(1000);
System.out.println("触发规则,500元-1000元 加500分");
end
5、DroolsDemoApplicationTests.java
package com.jin.rules;
import com.jin.rules.entity.Customer;
import com.jin.rules.entity.Order;
import org.drools.core.base.RuleNameEqualsAgendaFilter;
import org.junit.jupiter.api.Test;
import org.kie.api.KieServices;
import org.kie.api.runtime.KieContainer;
import org.kie.api.runtime.KieSession;
import org.springframework.boot.test.context.SpringBootTest;
import java.util.ArrayList;
@SpringBootTest
class DroolsDemoApplicationTests {
@Test
void contextLoads() {
//第一步:获取KieServices
KieServices kieServices = KieServices.Factory.get();
//第二步:获取kieContainer
KieContainer container = kieServices.getKieClasspathContainer("myKbase1");
//第三步:获取kieSession
KieSession kieSession = container.newKieSession("ksession-rule");
//事实对象
Order order = new Order();
order.setAmount(12);
// order.setAmount(121);
// order.setAmount(721);
// order.setAmount(1211);
//第四步:插入事实对象到session中
kieSession.insert(order);
//第五步:执行规则引擎
kieSession.fireAllRules();
//第六步:关闭规则引擎
kieSession.dispose();
System.out.println("执行规则后积分:"+order.getScore());
}
/**
* //测试contains
*/
@Test
void test01() {
//第一步:获取KieServices
KieServices kieServices = KieServices.Factory.get();
//第二步:获取kieContainer
KieContainer container = kieServices.getKieClasspathContainer();
//第三步:获取kieSession
KieSession kieSession = container.newKieSession();
//事实对象
Order order = new Order();
Customer customer = new Customer();
ArrayList<Order> orderList = new ArrayList<>();
orderList.add(order);
customer.setOrderList(orderList);
//第四步:插入事实对象到session中
kieSession.insert(order);
kieSession.insert(customer);
//第五步:执行规则引擎
kieSession.fireAllRules();
//第六步:关闭规则引擎
kieSession.dispose();
}
/**
* //测试not contains
* //测试比较操作符not matches
*/
@Test
void test02() {
//第一步:获取KieServices
KieServices kieServices = KieServices.Factory.get();
//第二步:获取kieContainer
KieContainer container = kieServices.getKieClasspathContainer();
//第三步:获取kieSession
KieSession kieSession = container.newKieSession();
//事实对象
Order order = new Order();
Customer customer = new Customer();
ArrayList<Order> orderList = new ArrayList<>();
// orderList.add(order);
customer.setOrderList(orderList);
//第四步:插入事实对象到session中
kieSession.insert(order);
kieSession.insert(customer);
//第五步:执行规则引擎
kieSession.fireAllRules();
//第六步:关闭规则引擎
kieSession.dispose();
}
/**
* //测试比较操作符matches
*/
@Test
void test03() {
//第一步:获取KieServices
KieServices kieServices = KieServices.Factory.get();
//第二步:获取kieContainer
KieContainer container = kieServices.getKieClasspathContainer();
//第三步:获取kieSession
KieSession kieSession = container.newKieSession();
//事实对象
Order order = new Order();
Customer customer = new Customer();
customer.setName("张三");
ArrayList<Order> orderList = new ArrayList<>();
// orderList.add(order);
customer.setOrderList(orderList);
//第四步:插入事实对象到session中
kieSession.insert(order);
kieSession.insert(customer);
//第五步:执行规则引擎
kieSession.fireAllRules();
//第六步:关闭规则引擎
kieSession.dispose();
}
/**
* //测试规则过滤器
*/
@Test
void test04() {
//第一步:获取KieServices
KieServices kieServices = KieServices.Factory.get();
//第二步:获取kieContainer
KieContainer container = kieServices.getKieClasspathContainer();
//第三步:获取kieSession
KieSession kieSession = container.newKieSession();
//事实对象
Order order = new Order();
Customer customer = new Customer();
customer.setName("张三");
ArrayList<Order> orderList = new ArrayList<>();
// orderList.add(order);
customer.setOrderList(orderList);
//第四步:插入事实对象到session中
kieSession.insert(order);
kieSession.insert(customer);
//第五步:执行规则引擎
//kieSession.fireAllRules();
kieSession.fireAllRules(new RuleNameEqualsAgendaFilter("rule_3"));
//kieSession.fireAllRules(new RuleNameEndsWithAgendaFilter("rule_3"));
//第六步:关闭规则引擎
kieSession.dispose();
}
}
三、02_droolsFunction
1、pom.xml
引入依赖
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.drools</groupId>
<artifactId>drools-compiler</artifactId>
<version>7.6.0.Final</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.kie</groupId>
<artifactId>kie-api</artifactId>
<version>7.6.0.Final</version>
<scope>test</scope>
</dependency>
</dependencies>
2、entity实体
2.1 Customer.java
package com.jin.rules.entity;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.util.List;
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Customer {
private String name;
private List<Order> orderList;
}
2.2 Order.java
package com.jin.rules.entity;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Order {
/**
* 订单金额
*/
private int amount;
/**
* 积分
*/
private int score;
}
3、META-INF.kmodule.xml
编写配置文件(resources.META-INF.kmodule.xml)
<?xml version="1.0" encoding="UTF-8"?>
<kmodule xmlns="http://www.drools.org/xsd/kmodule">
<!--
name:指定kbase的名称,可以任意,但是必须唯一
packages:指定规则文件的目录,需要根据实际情况填写,否则无法加载到规则文件
default:指定当前kbase是否为默认
-->
<kbase name="myKbase1" packages="rules" default="true">
<!--
name:指定ksession的名称,可以任意,但是必须唯一
default:指定当前ksession是否为默认
-->
<ksession name="ksession-rule" default="true"/>
</kbase>
</kmodule>
4、rules规则文件
customer-rules.drl
package rules;
import com.jin.rules.entity.*;
//1、Drools提供的内置方法insert
rule "rule_5"
no-loop true //避免死循环
when
eval(true);//默认成立
then
Customer customer = new Customer();
customer.setName("张三");
insert(customer);
//insertLogical(customer);
System.out.println("测试Drools提供的内置方法 insert 触发...");
end
rule "rule_6"
no-loop true //避免死循环
when
$customer:Customer(name == "张三");
then
System.out.println("测试Drools提供的内置方法 insert 触发..." + $customer.getName());
end
2、Drools提供的内置方法update
//rule "rule_7"
// no-loop true //避免死循环
// when
// $customer:Customer(name == "李四");
// then
// $customer.setName("王五");
// update($customer)
// System.out.println("测试Drools提供的内置方法 update 触发...");
//end
//
//rule "rule_8"
// no-loop true //避免死循环
// when
// $customer:Customer(name == "王五");
// then
// System.out.println("测试Drools提供的内置方法 update 触发..." + $customer.getName());
//end
3、Drools提供的内置方法retract
//rule "rule_9"
// no-loop true //避免死循环
// when
// $customer:Customer(name == "王五");
// then
// retract($customer)
// System.out.println("测试Drools提供的内置方法 retract 触发...");
//end
//
//rule "rule_8"
// no-loop true //避免死循环
// when
// $customer:Customer();
// then
// System.out.println("测试Drools提供的内置方法 retract 触发..." + $customer.getName());
//end
5、ApplicationTests.java
package com.jin.rules;
import com.jin.rules.entity.Customer;
import org.junit.jupiter.api.Test;
import org.kie.api.KieServices;
import org.kie.api.runtime.KieContainer;
import org.kie.api.runtime.KieSession;
import org.springframework.boot.test.context.SpringBootTest;
@SpringBootTest
class ApplicationTests {
@Test
void contextLoads() {
}
/**
* insert 函数
*/
@Test
void test05() {
//第一步:获取KieServices
KieServices kieServices = KieServices.Factory.get();
//第二步:获取kieContainer
KieContainer container = kieServices.getKieClasspathContainer();
//第三步:获取kieSession
KieSession kieSession = container.newKieSession();
//第五步:执行规则引擎
kieSession.fireAllRules();
//第六步:关闭规则引擎
kieSession.dispose();
}
/**
* update 函数
*/
@Test
void test06() {
//第一步:获取KieServices
KieServices kieServices = KieServices.Factory.get();
//第二步:获取kieContainer
KieContainer container = kieServices.getKieClasspathContainer();
//第三步:获取kieSession
KieSession kieSession = container.newKieSession();
//事实对象
Customer customer = new Customer();
customer.setName("李四");
//第四步:插入事实对象到session中
kieSession.insert(customer);
//第五步:执行规则引擎
kieSession.fireAllRules();
//第六步:关闭规则引擎
kieSession.dispose();
}
/**
* retract 函数
*/
@Test
void test07() {
//第一步:获取KieServices
KieServices kieServices = KieServices.Factory.get();
//第二步:获取kieContainer
KieContainer container = kieServices.getKieClasspathContainer();
//第三步:获取kieSession
KieSession kieSession = container.newKieSession();
//事实对象
Customer customer = new Customer();
customer.setName("王五");
//第四步:插入事实对象到session中
kieSession.insert(customer);
//第五步:执行规则引擎
kieSession.fireAllRules();
//第六步:关闭规则引擎
kieSession.dispose();
}
}
四、03_droolsProperty
1、pom.xml
引入依赖
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.drools</groupId>
<artifactId>drools-compiler</artifactId>
<version>7.6.0.Final</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.kie</groupId>
<artifactId>kie-api</artifactId>
<version>7.6.0.Final</version>
<scope>test</scope>
</dependency>
</dependencies>
2、entity实体
2.1 Customer.java
package com.jin.rules.entity;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.util.List;
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Customer {
private String name;
private List<Order> orderList;
}
2.2 Order.java
package com.jin.rules.entity;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Order {
/**
* 订单金额
*/
private int amount;
/**
* 积分
*/
private int score;
}
3、META-INF.kmodule.xml
编写配置文件(resources.META-INF.kmodule.xml)
<?xml version="1.0" encoding="UTF-8"?>
<kmodule xmlns="http://www.drools.org/xsd/kmodule">
<!--
name:指定kbase的名称,可以任意,但是必须唯一
packages:指定规则文件的目录,需要根据实际情况填写,否则无法加载到规则文件
default:指定当前kbase是否为默认
-->
<kbase name="myKbase1" packages="rules" default="true">
<!--
name:指定ksession的名称,可以任意,但是必须唯一
default:指定当前ksession是否为默认
-->
<ksession name="ksession-rule" default="true"/>
</kbase>
</kmodule>
4、rules规则文件
attributes-rules.drl
package rules;
import com.jin.rules.entity.*
import java.text.SimpleDateFormat
import java.util.Date;
//1、salience属性(数值越大优先级越高)
rule "attributes_rule1"
salience 1
when
eval(true)
then
System.out.println("rule1...");
end
rule "attributes_rule2"
salience 2
when
eval(true)
then
System.out.println("rule2...");
end
2、no-loop(为true时表示该规则只会被引擎检查一次)
//rule "attributes_rule3"
//salience 3
//no-loop true
// when
// $customer:Customer(name == "张三")
// then
// update($customer)
// System.out.println("死循环的customer name只被执行一次:" + $customer.getName());
//end
3、date-effective "yyyy-MM-dd"(只有当前系统时间>=date-effective设置的时间时执行)
//rule "attributes_rule4"
//salience 4
// date-effective "2022-12-04" //设置的日期不小于今天的日期可以执行
// when
// eval(true);
// then
// System.out.println("attributes_rule4 is execution!");
//end
4、date-expires "yyyy-MM-dd"(只有当前系统时间<=date-expires设置的时间时执行)
//rule "attributes_rule5"
//salience 5
// date-expires "2022-12-06" //设置的日期不大于今天的日期可以执行
// when
// eval(true);
// then
// System.out.println("attributes_rule5 is execution!");
//end
5、enabled(默认情况是true,为启动状态)
//rule "attributes_rule6"
//salience 6
// enabled false
// when
// eval(true);
// then
// System.out.println("attributes_rule6 is execution!");
//end
6、dialect ""(默认为java,也可以指定为mvel)
//rule "attributes_rule7"
//salience 7
//dialect "java"
// when
// eval(true);
// then
// System.out.println("attributes_rule7 is execution!");
//end
7、activation-group ""(设置一个组,随机指定一个执行,也可加入优先级让优先级高的执行)
//rule "attributes_rule8"
// activation-group "test"
// when
// eval(true);
// then
// System.out.println("attributes_rule8 is execution!");
//end
//
//
//rule "attributes_rule9"
// activation-group "test"
// when
// eval(true);
// then
// System.out.println("attributes_rule9 is execution!");
//end
8、agenda-group ""(设置不同的组,在Java中指定一个组进行引擎扫描)
//rule "attributes_rule10"
// agenda-group "001"
// when
// eval(true);
// then
// System.out.println("attributes_rule10 is execution!");
//end
//
//
//rule "attributes_rule11"
// agenda-group "002"
// auto-focus //自动获得焦点
// when
// eval(true);
// then
// System.out.println("attributes_rule11 is execution!");
//end
9、timer()
//rule "attributes_rule13"
// timer(5s 2s) //5s后触发,然后每隔2s触发一次
// when
// then
// System.out.println("attributes_rule13 is execution:触发时间为:" + new SimpleDateFormat("yyyy-MM-dd HH:m()m:ss").format(new Date()));
//end
//
//rule "attributes_rule14"
// timer(cron:0/1 * * * * ?) //每隔1s触发一次
// when
// then
// System.out.println("attributes_rule14 is execution:触发时间为:" + new SimpleDateFormat("yyyy-MM-dd HH:m()m:ss").format(new Date()));
//end
5、ApplicationTests.java
package com.jin.rules;
import com.jin.rules.entity.Customer;
import org.drools.core.base.RuleNameEqualsAgendaFilter;
import org.junit.jupiter.api.Test;
import org.kie.api.KieServices;
import org.kie.api.runtime.KieContainer;
import org.kie.api.runtime.KieSession;
import org.springframework.boot.test.context.SpringBootTest;
@SpringBootTest
class ApplicationTests {
@Test
void contextLoads() {
}
/**
* //1、salience属性(数值越大优先级越高)
*/
@Test
void test01() {
//第一步:获取KieServices
KieServices kieServices = KieServices.Factory.get();
//第二步:获取kieContainer
KieContainer container = kieServices.getKieClasspathContainer();
//第三步:获取kieSession
KieSession kieSession = container.newKieSession();
//第五步:执行规则引擎
kieSession.fireAllRules();
//第六步:关闭规则引擎
kieSession.dispose();
}
/**
* //2、no-loop(为true时表示该规则只会被引擎检查一次)
*/
@Test
void test02() {
//第一步:获取KieServices
KieServices kieServices = KieServices.Factory.get();
//第二步:获取kieContainer
KieContainer container = kieServices.getKieClasspathContainer();
//第三步:获取kieSession
KieSession kieSession = container.newKieSession();
//事实对象
Customer customer = new Customer();
customer.setName("张三");
//第四部:
kieSession.insert(customer);
//第五步:执行规则引擎
kieSession.fireAllRules();
//第六步:关闭规则引擎
kieSession.dispose();
}
/**
* //3、date-effective "yyyy-MM-dd"(只有当前系统时间>=date-effective设置的时间时执行)
*/
@Test
void test03() {
//设置日期格式(默认的日期格式为“dd-MMM-yyyy”)
System.setProperty("drools.dateformat","yyyy-MM-dd");
//第一步:获取KieServices
KieServices kieServices = KieServices.Factory.get();
//第二步:获取kieContainer
KieContainer container = kieServices.getKieClasspathContainer();
//第三步:获取kieSession
KieSession kieSession = container.newKieSession();
//第五步:执行规则引擎
kieSession.fireAllRules();
//第六步:关闭规则引擎
kieSession.dispose();
}
/**
* //4、date-expires "yyyy-MM-dd"(只有当前系统时间<=date-expires设置的时间时执行)
*/
@Test
void test04() {
//设置日期格式(默认的日期格式为“dd-MMM-yyyy”)
System.setProperty("drools.dateformat","yyyy-MM-dd");
//第一步:获取KieServices
KieServices kieServices = KieServices.Factory.get();
//第二步:获取kieContainer
KieContainer container = kieServices.getKieClasspathContainer();
//第三步:获取kieSession
KieSession kieSession = container.newKieSession();
//第五步:执行规则引擎
kieSession.fireAllRules();
//第六步:关闭规则引擎
kieSession.dispose();
}
/**
* //5、enabled(默认情况是true,为启动状态)
*/
@Test
void test05() {
//第一步:获取KieServices
KieServices kieServices = KieServices.Factory.get();
//第二步:获取kieContainer
KieContainer container = kieServices.getKieClasspathContainer();
//第三步:获取kieSession
KieSession kieSession = container.newKieSession();
//第五步:执行规则引擎
kieSession.fireAllRules(new RuleNameEqualsAgendaFilter("attributes_rule6"));
//第六步:关闭规则引擎
kieSession.dispose();
}
/**
* //6、dialect ""(默认为java,也可以指定为mvel)
*/
@Test
void test06() {
//第一步:获取KieServices
KieServices kieServices = KieServices.Factory.get();
//第二步:获取kieContainer
KieContainer container = kieServices.getKieClasspathContainer();
//第三步:获取kieSession
KieSession kieSession = container.newKieSession();
//第五步:执行规则引擎
kieSession.fireAllRules(new RuleNameEqualsAgendaFilter("attributes_rule7"));
//第六步:关闭规则引擎
kieSession.dispose();
}
/**
* //7、activation-group ""(设置一个组,随机指定一个执行,也可加入优先级让优先级高的执行)
*/
@Test
void test07() {
//第一步:获取KieServices
KieServices kieServices = KieServices.Factory.get();
//第二步:获取kieContainer
KieContainer container = kieServices.getKieClasspathContainer();
//第三步:获取kieSession
KieSession kieSession = container.newKieSession();
//第五步:执行规则引擎
kieSession.fireAllRules();
//第六步:关闭规则引擎
kieSession.dispose();
}
/**
* //8、agenda-group ""(设置不同的组,在Java中指定一个组进行引擎扫描)
*/
@Test
void test08() {
//第一步:获取KieServices
KieServices kieServices = KieServices.Factory.get();
//第二步:获取kieContainer
KieContainer container = kieServices.getKieClasspathContainer();
//第三步:获取kieSession
KieSession kieSession = container.newKieSession();
//活得执行焦点
//kieSession.getAgenda().getAgendaGroup("002").setFocus();
//第五步:执行规则引擎
kieSession.fireAllRules();
//第六步:关闭规则引擎
kieSession.dispose();
}
/**
* //9、timer()
*/
@Test
void test09() throws InterruptedException {
//第一步:获取KieServices
KieServices kieServices = KieServices.Factory.get();
//第二步:获取kieContainer
KieContainer container = kieServices.getKieClasspathContainer();
//第三步:获取kieSession
KieSession kieSession = container.newKieSession();
new Thread(new Runnable() {
@Override
public void run() {
kieSession.fireUntilHalt();
}
}).start();
Thread.sleep(10000); //sleep了10s
kieSession.halt();
//第五步:执行规则引擎
kieSession.fireAllRules();
//第六步:关闭规则引擎
kieSession.dispose();
}
}
五、04_droolsDeep
1、pom.xml
引入依赖
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.drools</groupId>
<artifactId>drools-compiler</artifactId>
<version>7.6.0.Final</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.kie</groupId>
<artifactId>kie-api</artifactId>
<version>7.6.0.Final</version>
<scope>test</scope>
</dependency>
</dependencies>
2、entity实体
2.1 Customer.java
package com.jin.rules.entity;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.util.List;
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Customer {
private String name;
private List<Order> orderList;
}
2.2 Order.java
package com.jin.rules.entity;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Order {
/**
* 订单金额
*/
private int amount;
/**
* 积分
*/
private int score;
}
2.3 Person.java
package com.jin.rules.entity;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Person {
private int age;
private String name;
}
3、META-INF.kmodule.xml
编写配置文件(resources.META-INF.kmodule.xml)
<?xml version="1.0" encoding="UTF-8"?>
<kmodule xmlns="http://www.drools.org/xsd/kmodule">
<!--
name:指定kbase的名称,可以任意,但是必须唯一
packages:指定规则文件的目录,需要根据实际情况填写,否则无法加载到规则文件
default:指定当前kbase是否为默认
-->
<kbase name="myKbase1" packages="rules" default="true">
<!--
name:指定ksession的名称,可以任意,但是必须唯一
default:指定当前ksession是否为默认
-->
<ksession name="ksession-rule" default="true"/>
</kbase>
</kmodule>
4、rules规则文件
high-rules.drl
package rules;
import com.jin.rules.entity.*
import java.util.List;
//定义全局变量
global List myGlobalList;
//1、global全局变量
rule "global_rule1"
when
eval(true)
then
myGlobalList.add("Hello world");
System.out.println("global_rule1 is execution...");
end
rule "global_rule2"
when
eval(true)
then
System.out.println("myGlobalList集合的元素个数:" + myGlobalList.size());
System.out.println("global_rule2 is execution...");
end
2、query查询
不带参数查询、当前query用于查询Working Memory中age>30的Person对象
//query "query_1"
// $person:Person(age>30)
//end
带参数查询、当前query用于查询Working Memory中age>30且参数为nameParam的Person对象
//query "query_2"(String nameParam)
// $person:Person(age>30,name == nameParam)
//end
3、function 函数
//function String fomat(String name){
// return "hello" + name;
//}
//
//rule "function_rule"
// when
// $person:Person(name != null && age > 30)
// then
// //调用上面定义的函数
// String fomat = fomat($person.getName());
// System.out.println(fomat);
//end
5、ApplicationTests.java
package com.jin.rules;
import com.jin.rules.entity.Person;
import org.junit.jupiter.api.Test;
import org.kie.api.KieServices;
import org.kie.api.runtime.KieContainer;
import org.kie.api.runtime.KieSession;
import org.kie.api.runtime.rule.QueryResults;
import org.kie.api.runtime.rule.QueryResultsRow;
import org.springframework.boot.test.context.SpringBootTest;
import java.util.ArrayList;
import java.util.List;
@SpringBootTest
class ApplicationTests {
@Test
void contextLoads() {
}
/**
* //1、global全局变量
*/
@Test
void test01() {
//第一步:获取KieServices
KieServices kieServices = KieServices.Factory.get();
//第二步:获取kieContainer
KieContainer container = kieServices.getKieClasspathContainer();
//第三步:获取kieSession
KieSession kieSession = container.newKieSession();
//设置一个全局变量
List<String> list = new ArrayList<>();
kieSession.setGlobal("myGlobalList",list);
//第五步:执行规则引擎
kieSession.fireAllRules();
//第六步:关闭规则引擎
kieSession.dispose();
System.out.println("规则执行完之后全局变量list的元素个数:" + list);
}
/**
* //2、query查询
*/
@Test
void test02() {
//第一步:获取KieServices
KieServices kieServices = KieServices.Factory.get();
//第二步:获取kieContainer
KieContainer container = kieServices.getKieClasspathContainer();
//第三步:获取kieSession
KieSession kieSession = container.newKieSession();
Person p1 = new Person();
p1.setAge(23);
p1.setName("Jack1");
kieSession.insert(p1);
Person p2 = new Person();
p2.setAge(56);
p2.setName("Jack2");
kieSession.insert(p2);
Person p3 = new Person();
p3.setAge(66);
p3.setName("Jack3");
kieSession.insert(p3);
//执行查询
QueryResults queryResults1 = kieSession.getQueryResults("query_1");
for (QueryResultsRow queryResult : queryResults1) {
Person p = (Person) queryResult.get("$person");
System.out.println(p);
}
System.out.println("--------------------------------------");
//执行查询
QueryResults queryResults2 = kieSession.getQueryResults("query_2","Jack3");
for (QueryResultsRow queryResult : queryResults2) {
Person p = (Person) queryResult.get("$person");
System.out.println(p);
}
//第五步:执行规则引擎
kieSession.fireAllRules();
//第六步:关闭规则引擎
kieSession.dispose();
}
/**
* //3、function 函数
*/
@Test
void test03() {
//第一步:获取KieServices
KieServices kieServices = KieServices.Factory.get();
//第二步:获取kieContainer
KieContainer container = kieServices.getKieClasspathContainer();
//第三步:获取kieSession
KieSession kieSession = container.newKieSession();
Person p1 = new Person();
p1.setAge(23);
p1.setName("Jack1");
kieSession.insert(p1);
Person p2 = new Person();
p2.setAge(56);
p2.setName("Jack2");
kieSession.insert(p2);
Person p3 = new Person();
p3.setAge(66);
p3.setName("Jack3");
kieSession.insert(p3);
//第五步:执行规则引擎
kieSession.fireAllRules();
//第六步:关闭规则引擎
kieSession.dispose();
}
}
六、05_droolsSpring
1、pom.xml
引入依赖
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.drools</groupId>
<artifactId>drools-core</artifactId>
<version>7.6.0.Final</version>
</dependency>
<dependency>
<groupId>org.drools</groupId>
<artifactId>drools-compiler</artifactId>
<version>7.6.0.Final</version>
</dependency>
<dependency>
<groupId>org.kie</groupId>
<artifactId>kie-api</artifactId>
<version>7.6.0.Final</version>
</dependency>
<dependency>
<groupId>org.kie</groupId>
<artifactId>kie-spring</artifactId>
<version>7.6.0.Final</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>compile</scope>
</dependency>
</dependencies>
2、entity实体
2.1 Order.java
package com.jin.rules.entity;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Order {
/**
* 订单金额
*/
private int amount;
/**
* 积分
*/
private int score;
}
3、rules规则文件
score-rules.drl
package rules;
import com.jin.rules.entity.Order;
//100元以下不加分
rule "score_1" //名称需唯一
when
//工作内存中必须存在Order这种类型的Fact对象 ---类型约束
//Fact对象的amount属性值必须小于等于100 ---属性约束
$sssss:Order(amount < 100);
then
$sssss.setScore(0);
System.out.println("触发规则,100元以下不加分");
end
//100元-500元 加100分
rule "score_2"
when
$order:Order(100 <= amount && amount<= 500)
then
$order.setScore(100);
System.out.println("触发规则,100元-500元 加100分");
end
//500元-1000元 加500分
rule "score_3"
when
$order:Order(500 < amount && amount <= 1000)
then
$order.setScore(500);
System.out.println("触发规则,500元-1000元 加500分");
end
//1000元以上 加1000分
rule "score_4"
when
$order:Order(1000 < amount)
then
$order.setScore(1000);
System.out.println("触发规则,500元-1000元 加500分");
end
4、规则引擎配置类
DroolsConfig.java
package com.jin.rules.config;
import org.kie.api.KieBase;
import org.kie.api.KieServices;
import org.kie.api.builder.KieBuilder;
import org.kie.api.builder.KieFileSystem;
import org.kie.api.builder.KieRepository;
import org.kie.api.runtime.KieContainer;
import org.kie.internal.io.ResourceFactory;
import org.kie.spring.KModuleBeanFactoryPostProcessor;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.core.io.support.ResourcePatternResolver;
import org.springframework.core.io.Resource;
import java.io.IOException;
/**
* 规则引擎配置类
*/
@Configuration
public class DroolsConfig {
//指定规则文件存放的目录
private static final String RULES_PATH = "rules/";
private final KieServices kieServices = KieServices.Factory.get();
@Bean
@ConditionalOnMissingBean
public KieFileSystem kieFileSystem() throws IOException {
System.setProperty("drools.dateformat","yyyy-MM-dd");
KieFileSystem kieFileSystem = kieServices.newKieFileSystem();
ResourcePatternResolver resourcePatternResolver =
new PathMatchingResourcePatternResolver();
Resource[] files =
resourcePatternResolver.getResources("classpath*:" + RULES_PATH + "*.*");
String path = null;
for (Resource file : files) {
path = RULES_PATH + file.getFilename();
kieFileSystem.write(ResourceFactory.newClassPathResource(path, "UTF-8"));
}
return kieFileSystem;
}
@Bean
@ConditionalOnMissingBean
public KieContainer kieContainer() throws IOException {
KieRepository kieRepository = kieServices.getRepository();
kieRepository.addKieModule(kieRepository::getDefaultReleaseId);
KieBuilder kieBuilder = kieServices.newKieBuilder(kieFileSystem());
kieBuilder.buildAll();
return kieServices.newKieContainer(kieRepository.getDefaultReleaseId());
}
@Bean
@ConditionalOnMissingBean
public KieBase kieBase() throws IOException {
return kieContainer().getKieBase();
}
@Bean
@ConditionalOnMissingBean
public KModuleBeanFactoryPostProcessor kiePostProcessor() {
return new KModuleBeanFactoryPostProcessor();
}
}
5、service业务层
RuleService.java
package com.jin.rules.service;
import com.jin.rules.entity.Order;
import org.kie.api.KieBase;
import org.kie.api.runtime.KieSession;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@Service
public class RuleService {
@Autowired
private KieBase kieBase;
public Order executeRule(Order order){
System.out.println(order);
KieSession kieSession = kieBase.newKieSession();
kieSession.insert(order);
kieSession.fireAllRules();
kieSession.dispose();
return order;
}
}
6、controller层
package com.jin.rules.controller;
import com.jin.rules.entity.Order;
import com.jin.rules.service.RuleService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("/rules/order")
public class OrderController {
@Autowired
private RuleService ruleService;
@RequestMapping("/saveOrder")
public Order saveOrder(@RequestBody Order order){
return ruleService.executeRule(order);
}
}
7、测试
此处为了便利本人在idea安装RestFulTool插件(也可使用Postman),利用RestFulTool插件进行测试如下
请求参数(入参):body
{
"amount": 520,
"score": 0
}
返回参数(出参):response
{
"amount": 520,
"score": 500
}
七、06_drools
1、数据库
1.建表rules
CREATE TABLE `rules` (
`id` int(11) NOT NULL,
`rules` varchar(255) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
2、插入一条规则数据
INSERT INTO `db_drools`.`rules`(`id`, `rules`) VALUES (1,
'package rules;
import com.jin.rules.bean.Message;
rule "rule01"
when
$message:Message(status == 0)
then
$message.setContent("hello,Drools Message!!!");
System.out.println("hello,Drools Message!!!");
end
');
2、application.properties
server.port=8009
application.main=com.jin.rules.Application
spring.datasource.url=jdbc:mysql://localhost:3306/db_drools?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=GMT
spring.datasource.username=root
spring.datasource.password=******
spring.datasource.driverClassName=com.mysql.cj.jdbc.Driver
mybatis.mapper-locations=classpath*:mapper/*Mapper.xml
3、pom.xml
引入依赖
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>1.3.2</version>
</dependency>
<dependency>
<groupId>org.drools</groupId>
<artifactId>drools-core</artifactId>
<version>7.6.0.Final</version>
</dependency>
<dependency>
<groupId>org.drools</groupId>
<artifactId>drools-compiler</artifactId>
<version>7.6.0.Final</version>
</dependency>
<dependency>
<groupId>org.drools</groupId>
<artifactId>drools-decisiontables</artifactId>
<version>7.6.0.Final</version>
</dependency>
<dependency>
<groupId>org.drools</groupId>
<artifactId>drools-templates</artifactId>
<version>7.6.0.Final</version>
</dependency>
<dependency>
<groupId>org.kie</groupId>
<artifactId>kie-api</artifactId>
<version>7.6.0.Final</version>
</dependency>
<dependency>
<groupId>org.kie</groupId>
<artifactId>kie-spring</artifactId>
<version>7.6.0.Final</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.16</version>
</dependency>
</dependencies>
4、bean实体
4.1 Message.java
package com.jin.rules.bean;
import java.io.Serializable;
public class Message implements Serializable {
private static final long serialVersionUID = 1L;
private String status;
private String content;
public String getStatus() {
return status;
}
public void setStatus(String status) {
this.status = status;
}
public String getContent() {
return content;
}
public void setContent(String content) {
this.content = content;
}
}
4.2 Rules.java
package com.jin.rules.bean;
public class Rules {
private Integer id;
private String rules;
public String getRules() {
return rules;
}
public void setRules(String rules) {
this.rules = rules;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
}
5、rules规则文件
rules.drl
#此处只需一个空的规则文件即可
6、mapper层
RulesDao.java
package com.jin.rules.dao;
import com.jin.rules.bean.Rules;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import org.springframework.stereotype.Repository;
@Repository
@Mapper
public interface RulesDao {
Rules getById (@Param("id")Integer id);
}
7、sql层
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.jin.rules.dao.RulesDao">
<select id="getById" parameterType="int" resultType="com.jin.rules.bean.Rules">
select *
from rules
where id = #{id}
</select>
</mapper>
8、service层
package com.jin.rules.service;
import com.jin.rules.bean.Message;
import com.jin.rules.bean.Rules;
import com.jin.rules.dao.RulesDao;
import org.drools.core.ClassObjectFilter;
import org.kie.api.KieBase;
import org.kie.api.KieServices;
import org.kie.api.builder.*;
import org.kie.api.runtime.KieContainer;
import org.kie.api.runtime.KieSession;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@Service
public class RulesService {
@Autowired
private RulesDao rulesDao;
public String executeRules(Integer id) {
String rules = "";
Rules ru = rulesDao.getById(id);
if (ru != null && ru.getRules() != null) {
rules = ru.getRules();
}
KieServices kieServices = KieServices.Factory.get();
KieFileSystem kfs = kieServices.newKieFileSystem();
kfs.write("src/main/resources/rules/rules.drl", rules.getBytes());
KieBuilder kieBuilder = kieServices.newKieBuilder(kfs).buildAll();
Results results = kieBuilder.getResults();
if (results.hasMessages(org.kie.api.builder.Message.Level.ERROR)) {
System.out.println(results.getMessages());
throw new IllegalStateException("### errors ###");
}
KieContainer kieContainer = kieServices.newKieContainer(kieServices.getRepository().getDefaultReleaseId());
KieBase kieBase = kieContainer.getKieBase();
KieSession ksession = kieBase.newKieSession();
Message message = new Message();
message.setStatus("0");
ksession.insert(message);
ksession.fireAllRules();
String result= null;
for (Object per : ksession.getObjects(new ClassObjectFilter(Message.class))) {
if (((Message) per).getStatus().equals("0")) {
result = ((Message) per).getContent();
}
}
return result;
}
}
9、controller层
package com.jin.rules.controller;
import com.jin.rules.bean.Rules;
import com.jin.rules.service.RulesService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
@Controller
@RequestMapping(value = "/rules")
public class RulesController {
@Autowired
private RulesService rulesService;
@RequestMapping(value ="/write" ,method = RequestMethod.POST)
public String getRuleByWrite(@RequestBody Rules rule) {
return rulesService.executeRules(rule.getId());
}
}
10、测试
此处为了便利本人在idea安装RestFulTool插件(也可使用Postman),利用RestFulTool插件进行测试如下
请求参数(入参):body
{
"id": 1,
"rules": "String"
}
返回参数(出参):response
<html>
<body><h1>Whitelabel Error Page</h1>
<p>This application has no explicit mapping for /error, so you are seeing this as a fallback.</p>
<div id='created'>Sun Apr 16 23:14:54 CST 2023</div>
<div>There was an unexpected error (type=Not Found, status=404).</div>
</body>
</html>
八、07_droolsDecision
一、决策表
对开发人员来说业务规则都是写在了drl文件中,这对开发人员来说是没有什么问题,如果是业务人员则不怎么友好,所以需要引入drools中决策表的使用,规则是写在excel文件中,通过上传决策表.xls到系统让其生成.drl文件,进行读取规则。
图中ResultSet和ResultTable是必须的,而且同一个包中,此处是一个简单的决策表。
参考官网:https://docs.drools.org/7.69.0.Final/drools-docs/html_single/index.html#decision-tables-con_decision-tables
二、RuleSet的属性
ResultSet:区域只可有一个。
Label | Value | Usage |
---|---|---|
RuleSet | 生成的DRL文件的程序包名称。可选,默认值为“rule_table”。 | 必须是第一个条目。 |
Sequential | `true或false。如果是“true”,则使用显著性来确保规则自上而下地启动。 | 可选,最多一次。如果省略,则不强制执行解雇令。 |
SequentialMaxPriority | 整数值 | 可选,最多一次。在顺序模式中,此选项用于设置显著性的起始值。如果省略,则默认值为65535。 |
SequentialMinPriority | 整数值 | 可选,最多一次。在顺序模式中,此选项用于检查是否未违反此最小显著性值。如果省略,则默认值为0。 |
EscapeQuotes | `true或false。如果“true”,则转义引号,以便它们在DRL中按字面意思出现。 | 可选,最多一次。如果省略,则转义引号。 |
IgnoreNumericFormat | `true或false。如果为“true”,则忽略数值的格式,例如百分比和货币。 | 可选,最多一次。如果省略,则DRL采用格式化的值。 |
Import | 要从另一个包导入的Java类的逗号分隔列表。 | 可选,可以重复使用。 |
Variables | DRL全局变量的声明(后面跟着变量名的类型)。多个全局定义必须用逗号分隔。 | 可选,可以重复使用。 |
Functions | 根据DRL语法的一个或多个查询定义。 | 可选,可以重复使用。 |
Declare | 根据DRL语法的一个或多个查询定义。 | 可选,可以重复使用。 |
Unit | 从此决策表生成的规则所属的规则单元。 | 可选,最多一次。如果省略,则这些规则不属于任何单位。 |
Dialect | java或mvel。在决策表的操作中使用的方言。 | 可选,最多一次。如果省略,则强制使用java。 |
三、RuleTable的属性
Label | Or custom label that begins with | Value | Usage |
---|---|---|---|
NAME | N | 提供从该行生成的规则的名称。默认值由RuleTable标记后面的文本和行号构成。 | 最多一列。 |
DESCRIPTION | I | 在生成的规则中产生注释。 | 最多一列。 |
CONDITION | C | 用于在条件中的模式内构造约束的代码段和插值。 | 每个规则表至少有一个。 |
ACTION | A | 用于为规则的结果构造操作的代码段和插值。 | 每个规则表至少有一个。 |
METADATA | @ | 用于构造规则的元数据项的代码段和插值。 | 可选,任意列数。 |
四、规则属性的编写
在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。
五、需求
我们需要根据学生的成绩分数,给出相应的结果。规则如下:
特殊处理的规则:
规则一:只要名字是张三的,直接判定为 优
规则二:只要名字是李四的,如果分数在0,60之间,直接认为是一般
普通规则:
规则三:分数在0,60之间认为是不及格
规则四:分数在60,70之间认为是一般
规则五:分数在70,90之间认为是良好
规则六:分数在90,100之间认为是优
从上方的规则中,我们可以看到姓名为张三和李四的学生特殊处理了。
六、开发
1、pom.xml
引入依赖
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.6.2</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.jin</groupId>
<artifactId>07_droolsDecision</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>07_droolsDecision</name>
<description>07_droolsDecision</description>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.drools</groupId>
<artifactId>drools-decisiontables</artifactId>
<version>7.6.0.Final</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.drools</groupId>
<artifactId>drools-compiler</artifactId>
<version>7.6.0.Final</version>
</dependency>
<dependency>
<groupId>org.kie</groupId>
<artifactId>kie-api</artifactId>
<version>7.6.0.Final</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>1.4.7</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<excludes>
<exclude>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</exclude>
</excludes>
</configuration>
</plugin>
</plugins>
</build>
</project>
2、bean实体
package com.jin.rules.bean;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@NoArgsConstructor
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;
}
}
3、META-INF.kmodule.xml
编写配置文件(resources.META-INF.kmodule.xml)
<kmodule xmlns="http://www.drools.org/xsd/kmodule">
<kbase name="kbase" packages="rules.decision.tables" default="false">
<ksession name="ksession" default="false" type="stateful"/>
</kbase>
</kmodule>
4、rules.decision.tables.student-score.xlsx
https://gitee.com/happy_sad/drools/tree/master/07_droolsDecision/src/main/resources/rules/decision/tables
5、测试
package com.jin.rules;
import com.jin.rules.bean.Student;
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));
// 赵六得69分,但是根据规则判断,结果应该是 一般
invokedDecisionTable(kieContainer, new Student("赵六", 69));
// 钱七得79分,但是根据规则判断,结果应该是 良好
invokedDecisionTable(kieContainer, new Student("钱七", 79));
// 李八得99分,但是根据规则判断,结果应该是 优
invokedDecisionTable(kieContainer, new Student("李八", 99));
}
/**
* 执行方法
* @param kieContainer
* @param student
*/
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());
}
}
}
}