Springboot整合规则引擎

Springboot整合Drools 规则引擎

1.添加maven 依赖坐标,并创建springboot项目

<!-- drools规则引擎 -->
<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.drools</groupId>
    <artifactId>drools-core</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>

2.建立相应代码结构

1,创建实体类

@Data
public class Person {
    private String names;

    private List<String> list;

}

3.在resources文件夹下创建META-INF 文件夹 和rules规则文件夹

META-INF下文件内容

<?xml version="1.0" encoding="UTF-8"?>
<kmodule xmlns="http://jboss.org/kie/6.0.0/kmodule">

    <!--
        name:指定kbase的名称,可以任意,但是需要唯一
        packages:指定规则文件的目录,需要根据实际情况填写,否则无法加载到规则文件
        default:指定当前kbase是否为默认 

    -->
    <kbase name="myKbase1" packages="rules" default="true">
        <!--
            name:指定ksession的名称,可以任意,但需要唯一
            default:指定当前session是否为默认
        -->
        <ksession name="ksession-rule" default="true"/>
    </kbase>
</kmodule>

Rules文件内容

package people;
import com.drools.demo.domain.Person
import com.drools.demo.service.DemoService
dialect "java"  #指定java语言
global DemoService demoService #设置全局变量
/**
 * 当前规则用于测试drools提供的操作运算符
    activation-group 同组只能又一个执行
    salience执行等级 salience 4 数值越大等级越高
 */

// 测试比较操作符contains #规则名称 全局唯一
rule "rule_comparison_contains"
    when
        Person(names contains "王小白")
    then
        demoService.test();

end

// 测试比较操作符contains
rule "rule_comparison_not_contains"
    when
        Person(names not contains "王小白") and
        Person(list not contains names)
    then
        System.out.println("规则:rule_comparison_not_contains触发了...");
end

// 测试比较操作符memberOf
rule "rule_comparison_memberOf"
    when
        Person(names memberOf list)
    then
        System.out.println("规则:rule_comparison_memberOf触发了...");

end

// 测试比较操作符not memberOf
rule "rule_comparison_not_memberOf"
    when
        Person(names not memberOf list)
    then
        System.out.println("规则:rule_comparison_not_memberOf触发了...");
end

// 测试比较操作符matches
rule "rule_comparison_matches"
    when
        Person(names matches "王.*") // 正则表达式
    then
        System.out.println("规则:rule_comparison_matches触发了...");
end

// 测试比较操作符not matches
rule "rule_comparison_not_matches"
    when
        Person(names not matches "王.*") // 正则表达式
    then
        System.out.println("规则:rule_comparison_not_matches触发了...");

end

4.代码测试

@RestController
public class TestDemoController {
    @Resource
    private DemoService demoService;
    @GetMapping("one")
    public void test(){
        KieServices kieServices = KieServices.Factory.get();
        // 获取Kie容器对象(默认容器对象
        KieContainer kieContainer = kieServices.newKieClasspathContainer();
        // 从Kie容器对象中获取会话对象(默认session对象
        KieSession kieSession = kieContainer.newKieSession();
        kieSession.setGlobal("demoService",demoService);
        Person fact = new Person();
        String names = "王小白";
        fact.setNames(names);
        List<String> list = new ArrayList<String>();
        list.add("小黑");
        list.add("王小白");
        list.add(names);
        fact.setList(list);
        // 将order对象插入工作内存
        kieSession.insert(fact);
        // 匹配对象
        // 激活规则,由drools框架自动进行规则匹配。若匹配成功,则执行
        kieSession.fireAllRules();
        // 关闭会话
        kieSession.dispose();
 }
}

Drools基础语法

package:包名,package对应的不⼀定是真正的⽬录,可以任意写com.abc,同⼀个包下的drl⽂ 件可以相互访问
import:⽤于导⼊类或者静态⽅法
global:全局变量
function:⾃定义函数
query:查询
rule end:规则体
规则体语法结构
⼀个规则通常包括三个部分:属性部分(attribute) 、条件部分(LHS)和结果部分(RHS)
rule “ruleName” //rule关键字,表示规则开始,参数为规则的唯⼀名称
attributes //规则属性,是rule与when之间的参数,为可选项
when //关键字,后⾯是规则的条件部分
LHS //Left Hand Side,是规则的条件部分
then //后⾯跟规则的结果部分
RHS //是规则的结果或⾏为
end

条件部分

LHS(Left Hand Side):是规则的条件部分的通⽤名称。它由零个或多个条件元素组成。如果LHS 为空,则它将被视为始终为true的条件元素。
LHS部分由⼀个或者多个条件组成,条件⼜称为pattern。
pattern的语法结构为:绑定变量名:Object(Field约束)

其中绑定变量名可以省略,通常绑定变量名的命名⼀般建议以$开始。如果定义了绑定变量名,就可以
在规则体的RHS部分使⽤此绑定变量名来操作相应的Fact对象。Field约束部分是需要返回true或者false 的0个或多个表达式。

//规则1:100元以下, 不加分
rule “score_1”
when
//⼯作内存中必须存在Order这种类型的Fact对象-----类型约束
//Fact对象的amout属性值必须⼩于等于100------属性约束
$s : Order(amout <= 100)
then
$s.setScore(0);
System.out.println("成功匹配到规则1:100元以下, 不加分 ");
end

如果 LHS 部分为空的话,那么引擎会⾃动添加⼀个 eval(true)的条件,由于该条件总是返回 true,所 以 LHS 为空的规则总是返回 true
1.约束连接
在 LHS 当中,可以包含 0~n 个条件,多个pattern之间可以采⽤“&&” (and) 、 “||”(or)和“,”(and) 来实现,也可以不写,默认连接为and
//规则2:100元-500元 加100分
rule “score_2”
when
$s : Order(amout > 100 && amout <= 500)
then
$s.setScore(100);
System.out.println("成功匹配到规则2:100元-500元 加100分 ");
end

2.⽐较操作符
在 Drools当中共提供了⼗⼆种类型的⽐较操作符, 分别是: >、 >=、 <、 <=、 = =、 !=、
contains、 not contains、memberof、not memberof、matches、not matches;在这⼗⼆种类型的 ⽐较操作符当中,前六个是⽐较常⻅也是⽤的⽐较多的⽐较操作符

示例:

第⼀步:创建实体类,⽤于测试⽐较操作符

package com.demo.entity; 
import java.util.List; 
public class Customer { 
//客户姓名 
private String name; 
private List<Order> orderList;//订单集合 
public String getName() { 
return name; 
} 
public void setName(String name) { 
this.name = name; 
} 
public List<Order> getOrderList() { 
return orderList; 
} 
public void setOrderList(List<Order> orderList) { 
this.orderList = orderList; 
} 
}

第⼆步:在/resources/rules下创建规则⽂件customer-rules.drl

package rules 
import com.chenj.entity.*; 
//测试contains规则 
rule "rule1" 
when 
$order:Order(); 
$customer:Customer(orderList contains $order); 
then 
System.out.println("测试contains规则触发:"+$customer.getName()); 
end 
//测试not contains规则 
rule "rule2" 
when 
$order:Order(); 
$customer:Customer(orderList not contains $order); 
then 
System.out.println("测试not contains规则触发:"+$customer.getName()); 
end 
//测试⽐较操作符matches 
rule "rule3" 
when 
Customer(name matches "张.*") 
then 
System.out.println("测试⽐较操作符matches触发..."); 
end 
//测试⽐较操作符not matches 
rule "rule4" 
when 
Customer(name not matches "张.*") 
then 
System.out.println("测试⽐较操作符not matches触发..."); 
end 

第三步:编写单元测试

@Test 
public void test2(){ 
KieServices kieServices = KieServices.Factory.get(); 
KieContainer kieContainer = 
kieServices.getKieClasspathContainer(); 
//会话对象,⽤于和规则引擎交互 
KieSession kieSession = kieContainer.newKieSession(); 
//构造订单对象,设置订单⾦额,由规则引擎计算获得的积分 
Order order = new Order(); 
//匹配规则:$order:Order(); 
kieSession.insert(order); 
Customer customer = new Customer(); 
List<Order> orderList = new ArrayList<>(); 
//匹配规则: $customer:Customer(orderList contains $order); 
//orderList.add(order); 
customer.setOrderList(orderList); 
customer.setName("Jack"); 
//将数据交给规则引擎,规则引擎会根据提供的数据进⾏规则匹配 
kieSession.insert(customer); 
//激活规则引擎,如果匹配成功则执⾏规则 
kieSession.fireAllRules(); 
//关闭会话 
kieSession.dispose(); 
} 

在 Drools 当中,在 RHS ⾥⾯,提供了⼀些对当前 Working Memory 实现快速操作的宏宏函数或对
象, ⽐如 insert/insertLogical、 update 和 retract 就可以实现对当前 Working Memory中的 Fact
对象进⾏新增、删除或者是修改
1.insert
函数insert的作⽤与我们在Java类当中调⽤StatefulKnowledgeSession对象的insert⽅法的作⽤相同,
都是⽤来将⼀个 Fact 对象插⼊到当前的 Working Memory 当中
需注意:⼀旦调⽤ insert 宏函数,那么 Drools 会重新与所有的规则再重新匹配⼀次, 对于没有设置
no-loop 属性为 true 的规则,如果条件满⾜,不管其之前是否执⾏过都会再执⾏⼀次,这个特性不仅
存在于 insert 宏函数上,后⾯介绍的 update、retract 宏函数同样具有该特性,所以在某些情况下因考
虑不周调⽤ insert、update 或 retract 容易发⽣死循环

//Drools提供的内置⽅法insert
rule “rule5”
when
eval(true); //默认成⽴
then
Customer cus=new Customer();
cus.setName(“张三”);
insert(cus);
System.out.println(“测试Drools提供的内置⽅法insert 触发…”);
end
rule “rule6”
when
c u s t o m e r : C u s t o m e r ( n a m e = = " 张三 " ) ; t h e n S y s t e m . o u t . p r i n t l n ( " 测试 D r o o l s 提供的内置⽅法 i n s e r t 触发 . . . " + customer:Customer(name =="张三"); then System.out.println("测试Drools提供的内置⽅法insert 触 发..."+ customer:Customer(name=="张三");thenSystem.out.println("测试Drools提供的内置insert触发..."+customer.getName());
end

测试:
@Test
public void test3(){
KieServices kieServices = KieServices.Factory.get();
KieContainer kieContainer =
kieServices.getKieClasspathContainer();
//会话对象,⽤于和规则引擎交互
KieSession kieSession = kieContainer.newKieSession();
//激活规则引擎,如果匹配成功则执⾏规则
kieSession.fireAllRules();
//关闭会话
kieSession.dispose();
}

2.Update
update函数意义与其名称⼀样, ⽤来实现对当前Working Memory当中的 Fact进⾏更新,⽤来告诉当 前的 Working Memory 该 Fact 对象已经发⽣了变化
示例:
rule “rule7”
//no-loop true
when
$customer:Customer(name ==“李四”);
then
c u s t o m e r . s e t N a m e ( " 张三 " ) ; u p d a t e ( customer.setName("张三"); update( customer.setName("张三");update(customer);
System.out.println(“测试Drools提供的内置⽅法update 触发…”);
end
rule “rule8”
when
c u s t o m e r : C u s t o m e r ( n a m e = = " 张三 " ) ; t h e n S y s t e m . o u t . p r i n t l n ( " 测试 D r o o l s 提供的内置⽅法 u p d a t e 触发 . . . " + customer:Customer(name =="张三"); then System.out.println("测试Drools提供的内置⽅法update 触 发..."+ customer:Customer(name=="张三");thenSystem.out.println("测试Drools提供的内置update触发..."+customer.getName());
end

测试
@Test
public void test3(){
KieServices kieServices = KieServices.Factory.get();
KieContainer kieContainer =
kieServices.getKieClasspathContainer();
//会话对象,⽤于和规则引擎交互
KieSession kieSession = kieContainer.newKieSession();
Customer customer = new Customer();
customer.setName(“李四”);
kieSession.insert(customer);
//激活规则引擎,如果匹配成功则执⾏规则
kieSession.fireAllRules();
//关闭会话
kieSession.dispose();
}

3.retract
retract⽤来将 Working Memory 当中某个 Fact 对象从 Working Memory 当中删除
//Drools提供的内置⽅法retract
rule “rule9”
when
c u s t o m e r : C u s t o m e r ( n a m e = = " 李四 " ) ; t h e n / / r e t r a c t ( customer:Customer(name =="李四"); then //retract( customer:Customer(name=="李四");then//retract(customer);
System.out.println(“测试Drools提供的内置⽅法retract 触发…”);
end
rule “rule10”
when
c u s t o m e r : C u s t o m e r ( ) ; t h e n S y s t e m . o u t . p r i n t l n ( " 测试 D r o o l s 提供的内置⽅法 r e t r a c t 触发 . . . " + customer:Customer(); then System.out.println("测试Drools提供的内置⽅法retract 触 发..."+ customer:Customer();thenSystem.out.println("测试Drools提供的内置retract触发..."+customer.getName());
end

测试
@Test
public void test3(){
KieServices kieServices = KieServices.Factory.get();
KieContainer kieContainer =
kieServices.getKieClasspathContainer();
//会话对象,⽤于和规则引擎交互
KieSession kieSession = kieContainer.newKieSession();
Customer customer = new Customer();
customer.setName(“李四”);
kieSession.insert(customer);
//激活规则引擎,如果匹配成功则执⾏规则
kieSession.fireAllRules();
//通过规则过滤器实现只执⾏指定规则
//kieSession.fireAllRules(new
RuleNameEqualsAgendaFilter(“rule5”));
//关闭会话
kieSession.dispose();
}

属性部分
Drools中提供的属性如下表:
Springboot整合规则引擎_第1张图片

你可能感兴趣的:(SpringBoot,spring,boot,后端)