zxpnet网站 zxpnet网站
首页
前端
后端服务器
  • 分类
  • 标签
  • 归档
GitHub (opens new window)

zxpnet

一个爱学习的java开发攻城狮
首页
前端
后端服务器
  • 分类
  • 标签
  • 归档
GitHub (opens new window)
  • 大后端课程视频归档
  • 南航面试题
  • 并发编程

  • 性能调优

  • java8语法

  • lombok

  • 日志

  • 工具类

    • guava基础
    • jsoup
    • drools规则引擎
      • HelloWord
        • 1、编写/META-INF/kmodule.xml配置文件
        • 2、resources/rules 新建XXX.drl规则文件
        • 3、组装
      • 原理
        • 规则引擎构成
        • 规则引擎执行过程
      • drools语法
        • 1、规则文件构成
        • 2、规则体语法结构
        • 3、注释
        • 4、条件部分模式匹配
        • 5、结果部分RHS
        • 6、属性部分
      • Drools高级语法
        • global全局变量
        • query查询
        • function函数
        • LHS加强
        • RHS加强
      • 整合springboot
      • workbench
    • archaius
  • spring

  • mybatis

  • springboot

  • redis

  • zookeeper

  • springcloud

  • dubbo

  • netty

  • springsecurity

  • mq消息中间件

  • shiro

  • beetle

  • 模板引擎

  • jpa

  • 数据结构与算法

  • 数据库知识与设计

  • gradle

  • maven

  • bus

  • 定时任务

  • docker

  • centos

  • 加解密

  • biz业务

  • pigx项目

  • 开源项目

  • 品达通用权限项目-黑马

  • 货币交易项目coin-尚学堂

  • php

  • backend
  • 工具类
shollin
2021-12-13
目录

drools规则引擎

  • HelloWord
  • 原理
    • 规则引擎构成
    • 规则引擎执行过程
  • drools语法
    • 1、规则文件构成
    • 2、规则体语法结构
    • 3、注释
    • 4、条件部分模式匹配
    • 5、结果部分RHS
    • 6、属性部分
  • Drools高级语法
    • global全局变量
    • query查询
    • function函数
    • LHS加强
    • RHS加强
  • 整合springboot
  • workbench

# HelloWord

Drools Jar 包介绍:

knowledge-api.jar - 提供接口和工厂。它清楚地描述用户 API 的职责,还有什么引擎 API。 knowledge-internal-api.jar - 提供内部接口和工厂。 drools-core.jar - 核心引擎,运行时组件。包含 RETE 引擎和 LEAPS 引擎。 drools-compiler.jar - 包含编译器/构建器组件,以获取规则源,并构建可执行规则库。 drools-decisiontables.jar - 决策表编译器组件,在 drools-compiler 组件中使用。支持 Excel 和 CSV 输入格式。

<dependency>
    <groupId>org.kie</groupId>
    <artifactId>kie-api</artifactId>
</dependency>
<dependency>
    <groupId>org.drools</groupId>
    <artifactId>drools-compiler</artifactId>
</dependency>
<dependency>
    <groupId>junit</groupId>
    <artifactId>junit</artifactId>
    <version>4.12</version>
</dependency>

<dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.drools</groupId>
                <artifactId>drools-bom</artifactId>
                <version>${drools.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>

            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-dependencies</artifactId>
                <version>${spring-boot.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
</dependencyManagement>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33

# 1、编写/META-INF/kmodule.xml配置文件

<?xml version="1.0" encoding="UTF-8" ?>
<kmodule xmlns="http://www.drools.org/xsd/kmodule">
    <!--
        name:指定kbase的名称,可以任意,但是需要唯一
        packages:指定drl规则文件内的包名,需要根据实际情况填写,否则无法加载到规则文件
        default:指定当前kbase是否为默认
    -->
    <kbase name="myKbase1" packages="com.zxp.rules"  default="true">
        <!--
            name:指定ksession名称,可以任意,但是需要唯一
            default:指定当前session是否为默认
        -->
        <ksession name="ksession-rule" default="true"/>
    </kbase>
</kmodule>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

# 2、resources/rules 新建XXX.drl规则文件

package com.zxp.rules // 包名,与kmodule.xml保持一致
import com.zxp.drools.bean.Order

//规则一:所购图书总价在100元以下的没有优惠
rule "book_discount_1"
    when
        $order:Order(originalPrice < 100)
    then
        $order.setRealPrice($order.getOriginalPrice());
        System.out.println("成功匹配到规则一:所购图书总价在100元以下的没有优惠");
end
1
2
3
4
5
6
7
8
9
10
11

# 3、组装

@Test
    public void test1() {
        KieServices kieServices = KieServices.Factory.get();
        KieContainer kieClasspathContainer = kieServices.getKieClasspathContainer();
        //会话对象,用于和规则引擎交互
        KieSession kieSession = kieClasspathContainer.newKieSession();

        //构造订单对象,设置原始价格,由规则引擎根据优惠规则计算优惠后的价格
        Order order = new Order();
        order.setOriginalPrice(210d);

        //将数据提供给规则引擎,规则引擎会根据提供的数据进行规则匹配
        kieSession.insert(order);

        //激活规则引擎,可以指定过滤器,如果规则匹配成功则执行规则
        kieSession.fireAllRules();       
        // kieSession.fireAllRules(new RuleNameEqualsAgendaFilter("rule-1"));
        
        //关闭会话
        kieSession.dispose();

        System.out.println("优惠前原始价格:" + order.getOriginalPrice() +
                ",优惠后价格:" + order.getRealPrice());
    }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24

开发步骤

    • 获取KieService
    • 获取kieContainer
    • 获取KieSession
    • Insert Fact
    • 触发规则
    • 关闭kieSession

9

# 原理

image-20211213145528693

在这里插入图片描述

# 规则引擎构成

drools规则引擎由以下三部分构成:

  • Working Memory(工作内存),drools规则引擎会从Working Memory中获取数据并和规则文件中定义的规则进行模式匹配。

    • Fact : 事实,我们把一个javaBean插入到Working Memory后的对象就是Fact对象。
  • Rule Base(规则库),我们在规则文件中定义的规则都会被加载到规则库中。

  • Inference Engine(推理引擎)

    • Pattern Matcher,(匹配器)将Rule Base中的所有规则与Working Memory中的Fact对象进行模式匹配,匹配成功的规则将被激活并放入Agenda中。
    • Agenda(议程),用于存放通过匹配器进行模式匹配后被激活的规则。
    • Execution Engine(执行引擎),执行Agenda中被激活的规则。

如图:

img

在这里插入图片描述

# 规则引擎执行过程

img

# drools语法

# 1、规则文件构成

在使用Drools时非常重要的一个工作就是编写规则文件,通常规则文件的后缀为.drl,drl是Drools Rule Language的缩写。在规则文件中编写具体的规则内容。

一套完整的规则文件内容构成如下:

img

Drools支持的规则文件,除了drl形式,还有Excel文件类型的。

package package-name

imports

globals

functions

queries

rules
1
2
3
4
5
6
7
8
9
10
11

# 2、规则体语法结构

规则体是规则文件内容中的重要组成部分,是进行业务规则判断、处理业务结果的部分。

规则体语法结构如下:

rule "ruleName"
    attributes
    when
        LHS
    then
        RHS
end
1
2
3
4
5
6
7

rule:关键字,表示规则开始,参数为规则的唯一名称。

attributes:规则属性,是rule与when之间的参数,为可选项。

when:关键字,后面跟规则的条件部分。条件可以不写,默认就是eval(true)

LHS(Left Hand Side):是规则的条件部分的通用名称。它由零个或多个条件元素组成。如果LHS为空,则它将被视为始终为true的条件元素。

then:关键字,后面跟规则的结果部分。

RHS(Right Hand Side):是规则的后果或行动部分的通用名称。

end:关键字,表示一个规则结束。

# 3、注释

在drl形式的规则文件中使用注释和Java类中使用注释一致,分为单行注释和多行注释。

单行注释用"//"进行标记,多行注释以"/"开始,以"/"结束。如下示例:

//规则rule1的注释,这是一个单行注释
rule "rule1"
    when
    then
        System.out.println("rule1触发");
end

/*
规则rule2的注释,
这是一个多行注释
*/
rule "rule2"
    when
    then
        System.out.println("rule2触发");
end
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

# 4、条件部分模式匹配

Drools中的匹配器可以将Rule Base中的所有规则与Working Memory中的Fact对象进行模式匹配,那么我们就需要在规则体的LHS部分定义规则并进行模式匹配。LHS部分由一个或者多个条件组成,条件又称为pattern。

pattern的语法结构为:绑定变量名:Object(Field约束)

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

  • **eval(true):**是一个默认的api,true 无条件执行,类似于 while(true)
  • 操作符:>、>=、<、<=、==、!=、contains、not contains、memberOf、not memberOf、matches、not matches

img

  • contains: 对比是否包含操作,操作的被包含目标可以是一个复杂对象也可以是一个简单的值 Person( fullName not contains "Jr" )
  • **not contains:**与contains相反。
  • **memberOf:**判断某个Fact属性值是否在某个集合中,与contains不同的是他被比较的对象是一个集合,而contains被比较的对象是单个值或者对象 CheeseCounter( cheese memberOf $matureCheeses )
  • not memberOf:与memberOf正好相反
  • matches:正则表达式匹配 Cheese( type matches "(Buffalo)?\\S*Mozarella" ) 注意: 就像在Java中,写为字符串的正则表达式需要转义“\”
  • **not matches:**与matches正好相反

# 5、结果部分RHS

  • **insert:**往当前workingMemory中插入一个新的Fact对象,会触发规则的再次执行,除非使用no-loop true限定(只会匹配一次)。 要防止发生死循环
  • **update:**更新
  • **modify:**修改,与update语法不同,结果都是更新操作
  • **retract:**删除
动作 描述
set 给属性赋值
modify 将改变通知drools引擎
update 将改变通知drools引擎
insert 将新事实插入到drools引擎的工作
insertLogical insert增强版,需声明撤回事件,或待不在匹配条件后自动撤回
delete 删除事实

# 6、属性部分

属性名 说明
salience 指定规则执行优先级,数值越大,优先级别越高
dialect 指定规则使用的语言类型,取值为java和mvel
enabled 指定规则是否启用
date-effective 指定规则生效时间,大于时执行,默认日期格式为dd-MMM-yyyy用户也可以自定义日期格式,System.setProperty("drools.dateformat","yyyy-MM-dd");
date-expires 指定规则失效时间,即只有当前系统时间小于设置的时间或者日期规则才有可能触发。默认日期格式为:dd-MMM-yyyy用户也可以自定义日期格式
activation-group 激活分组,具有相同分组名称的规则只能有一个规则触发,可以与salience搭配
agenda-group 议程分组,只有获取焦点的组中的规则才有可能触发,kieSession.getAgenda().getAgendaGroup("rule-AG1").setFocus();
timer 定时器,指定规则触发的时间,timer(5s 2s) 第一个参数延时时间,第二个参数为间隔时间(可选); cron表达式timer (cron:0/1 * * * * ?)
auto-focus 自动获取焦点,一般结合agenda-group一起使用
no-loop 防止死循环,为true,只执行一次,当规则通过update之类的函数修改了Fact对象时,可能使当前规则再次被激活从而导致死循环

# Drools高级语法

# global全局变量

global关键字用于在规则文件中定义全局变量,它可以让应用程序的对象在规则文件中能够被访问。可以用来为规则文件提供数据或服务。

语法结构为:global 对象类型 对象名称

在使用global定义的全局变量时有两点需要注意:

1、如果对象类型为包装类型时,在一个规则中改变了global的值,那么只针对当前规则有效,对其他规则中的global不会有影响。可以理解为它是当前规则代码中的global副本,规则内部修改不会影响全局的使用。

2、如果对象类型为集合类型或JavaBean时,在一个规则中改变了global的值,对java代码和所有规则都有效

// .drl文件中
global java.lang.Integer count //定义一个包装类型的全局变量
global java.util.List gList  //定义一个集合类型的全局变量
global UserService userService //定义一个JavaBean类型的全局变量


//设置全局变量,名称和类型必须和规则文件中定义的全局变量名称对应
kieSession.setGlobal("count", 5);

List<String> list = new ArrayList<String>();
list.add("itheima");
kieSession.setGlobal("gList", list);

kieSession.setGlobal("userService", new UserService());
1
2
3
4
5
6
7
8
9
10
11
12
13
14

# query查询

query查询提供了一种查询working memory中符合约束条件的Fact对象的简单方法。它仅包含规则文件中的LHS部分,不用指定“when”和“then”部分并且以end结束

query 'query-1'
    $person:Person(age>30)
end

query 'query-2'(String nameParam)
    $person:Person(age>30 , name==nameParam)
end
1
2
3
4
5
6
7
QueryResults queryResults = kieSession.getQueryResults("query-1");
for (QueryResultsRow row:queryResults) {
            Person p = (Person) row.get("$person");
            System.out.println(p);
}
1
2
3
4
5

# function函数

function关键字用于在规则文件中定义函数,就相当于java类中的方法一样。可以在规则体中调用定义的函数。使用函数的好处是可以将业务逻辑集中放置在一个地方,根据需要可以对函数进行修改。

# LHS加强

在规则体中的LHS部分是介于when和then之间的部分,主要用于模式匹配,只有匹配结果为true时,才会触发RHS部分的执行。

5.4.1、复合值限制in/not in

复合值限制是指超过一种匹配值的限制条件,类似于SQL语句中的in关键字。Drools规则体中的LHS部分可以使用in或者not in进行复合值的匹配。具体语法结构如下:

Object(field in (比较值1,比较值2...))

举例:

$s:Student(name in ("张三","李四","王五"))
$s:Student(name not in ("张三","李四","王五"))
1
2

5.4.2、条件元素eval

eval用于规则体的LHS部分,并返回一个Boolean类型的值。语法结构如下:

eval(表达式)

举例:

eval(true)
eval(false)
eval(1 == 1)
1
2
3

5.4.3、条件元素not

not用于判断Working Memory中是否存在某个Fact对象,如果不存在则返回true,如果存在则返回false。语法结构如下:

not Object(可选属性约束)

举例:

not Student()
not Student(age < 10)
1
2

5.4.4、条件元素exists

exists的作用与not相反,用于判断Working Memory中是否存在某个Fact对象,如果存在则返回true,不存在则返回false。语法结构如下:

exists Object(可选属性约束)

举例:

exists Student()
exists Student(age < 10 && name != null)
1
2

在LHS部分进行条件编写时并没有使用exists也可以达到判断Working Memory中是否存在某个符合条件的Fact元素的目的,那么我们使用exists还有什么意义?

两者的区别:当向Working Memory中加入多个满足条件的Fact对象时,使用了exists的规则执行一次,不使用exists的规则会执行多次。

例如:

规则文件(只有规则体):

rule "使用exists的规则"
    when
        exists Student()
    then
        System.out.println("规则:使用exists的规则触发");
end

rule "没有使用exists的规则"
    when
        Student()
    then
        System.out.println("规则:没有使用exists的规则触发");
end
1
2
3
4
5
6
7
8
9
10
11
12
13

Java代码:

kieSession.insert(new Student());
kieSession.insert(new Student());
kieSession.fireAllRules();
1
2
3

上面第一个规则只会执行一次,因为Working Memory中存在两个满足条件的Fact对象,第二个规则会执行两次。

5.4.5、规则继承

规则之间可以使用extends关键字进行规则条件部分的继承,类似于java类之间的继承。

例如:

rule "rule_1"
    when
        Student(age > 10)
    then
        System.out.println("规则:rule_1触发");
end

rule "rule_2" extends "rule_1" //继承上面的规则
    when
        /*
        此处的条件虽然只写了一个,但是从上面的规则继承了一个条件,
        所以当前规则存在两个条件,即Student(age < 20)和Student(age > 10)
        */
        Student(age < 20) 
    then
        System.out.println("规则:rule_2触发");
end
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

需要注意的是,只继承条件

# RHS加强

RHS部分是规则体的重要组成部分,当LHS部分的条件匹配成功后,对应的RHS部分就会触发执行。一般在RHS部分中需要进行业务处理。

在RHS部分Drools为我们提供了一个内置对象,名称就是drools。

5.5.1、halt

halt方法的作用是立即终止后面所有规则的执行。

package testhalt
rule "rule_halt_1"
    when
    then
        System.out.println("规则:rule_halt_1触发");
        drools.halt();//立即终止后面所有规则执行
end

//当前规则并不会触发,因为上面的规则调用了halt方法导致后面所有规则都不会执行
rule "rule_halt_2"
    when
    then
        System.out.println("规则:rule_halt_2触发");
end
1
2
3
4
5
6
7
8
9
10
11
12
13
14

5.5.2、getWorkingMemory

getWorkingMemory方法的作用是返回工作内存对象。

package testgetWorkingMemory
rule "rule_getWorkingMemory"
    when
    then
        System.out.println(drools.getWorkingMemory());
end
1
2
3
4
5
6

5.5.3、getRule

getRule方法的作用是返回规则对象。

package testgetRule
rule "rule_getRule"
    when
    then
        System.out.println(drools.getRule());
end
1
2
3
4
5
6

img

5.6、规则文件编写规范

我们在进行drl类型的规则文件编写时尽量遵循如下规范:

  • 所有的规则文件(.drl)应统一放在一个规定的文件夹中,如:/rules文件夹

  • 书写的每个规则应尽量加上注释。注释要清晰明了,言简意赅

  • 同一类型的对象尽量放在一个规则文件中,如所有Student类型的对象尽量放在一个规则文件中

  • 规则结果部分(RHS)尽量不要有条件语句,如if(...),尽量不要有复杂的逻辑和深层次的嵌套语句

  • 每个规则最好都加上salience属性,明确执行顺序

  • Drools默认dialect为"Java",尽量避免使用dialect "mvel"

# 整合springboot

# workbench

参考视频:

Drools规则引擎讲解教程,从入门到整合实战_哔哩哔哩_bilibili (opens new window)

参考文档:

Drools学习小结 · 语雀 (yuque.com) (opens new window)

jsoup
archaius

← jsoup archaius→

最近更新
01
国际象棋
09-15
02
成语
09-15
03
自然拼读
09-15
更多文章>
Theme by Vdoing | Copyright © 2019-2023 zxpnet | 粤ICP备14079330号-1
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式