Springboot整合规则引擎

news2024/11/17 23:44:16

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中提供的属性如下表:
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1011933.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

maven-resources-production:trunk-auth: java.lang.NegativeArraySizeException

ijdea启动auth项目报错&#xff1a; maven-resources-production:trunk-auth: java.lang.NegativeArraySizeException 一直在本地启动不起来&#xff0c;记录下操作步骤 第一步&#xff1a;将ijdea中的缓存都清理掉了&#xff0c;不行 第二步&#xff1a;将maven中的对应项目…

如何将内网ip映射到外网?快解析内网穿透

关于内网ip映射到外网的问题&#xff0c;就是网络地址转换&#xff0c;私网借公网。要实现这个&#xff0c;看起来说得不错&#xff0c;实际上是有前提条件的。要实现内网ip映射到外网&#xff0c;首先要有一个固定的公网IP&#xff0c;可以从运营商那里得到。当你得到公网IP后…

Mybatis动态数据源及其原理

一、引言 作者最近的平台项目需要一个功能&#xff0c;数据库是动态的&#xff0c;sql也是动态的&#xff0c;所以需要动态注入数据源&#xff0c;并且能够在运行过程中进行切换数据库。作者在这里分享一下做法&#xff0c;以及Mybatis这样做的原理。 二、分析 接下来分析一下…

【案例教学】华为云API图引擎服务 GES的便捷性—AI帮助快速处理图片小助手

云服务、API、SDK&#xff0c;调试&#xff0c;查看&#xff0c;我都行 阅读短文您可以学习到&#xff1a;人工智能AI快速处理图片 1 IntelliJ IDEA 之API插件介绍 API插件支持 VS Code IDE、IntelliJ IDEA等平台、以及华为云自研 CodeArts IDE&#xff0c;基于华为云服务提供…

LeetCode //C - 637. Average of Levels in Binary Tree

637. Average of Levels in Binary Tree Given the root of a binary tree, return the average value of the nodes on each level in the form of an array. Answers within 1 0 − 5 10^{-5} 10−5 of the actual answer will be accepted. Example 1: Input: root [3…

学Python的漫画漫步进阶 -- 第十三步

学Python的漫画漫步进阶 -- 第十三步 十三、图形用户界面13.1 Python中的图形用户界面开发库13.2 安装wxPython13.3 第一个wxPython程序13.4 自定义窗口类13.5 在窗口中添加控件13.6 事件处理13.7 布局管理13.7.1 盒子布局管理器13.7.2 动动手——重构事件处理示例13.7.3 动动手…

赴日开发工程师工作怎么找?

想要做赴日开发工作的途径有一下几种&#xff1a;一个是自己去联系日本的企业&#xff0c;当然这种的前提是你日语完全没有问题&#xff0c;但是现在很少有企业愿意直接与求职人员沟通。第二个就是你有IT技术&#xff0c;但是不会日语&#xff0c;年纪不大的可以来日本读个学校…

单目标追踪——【工具】汉明窗(Hamming window)

目录 汉明窗&#xff08;Hamming window&#xff09;原理作用代码实例可视化总结 汉明窗&#xff08;Hamming window&#xff09; 原理 汉明&#xff08;Hanning&#xff09;窗可以看成是升余弦窗的一个特例&#xff0c;汉宁窗可以看作是3个矩形时间窗的频谱之和&#xff0c;…

webpack实战:最新QQ音乐sign参数加密分析

文章目录 1. 写在前面2. 接口抓包分析3. 扣webpack代码4. 补浏览器环境5. 验证加密结果 1. 写在前面 现在&#xff01;很多的网站使用Webpack加载和处理JS文件。所以对于使用了Webpack加载的JS代码&#xff0c;一旦它们被打包并在浏览器中执行&#xff0c;通常是难以直接阅读和…

选择正确的开发框架:构建高效、可维护的应用程序

&#x1f482; 个人网站:【工具大全】【游戏大全】【神级源码资源网】&#x1f91f; 前端学习课程&#xff1a;&#x1f449;【28个案例趣学前端】【400个JS面试题】&#x1f485; 寻找学习交流、摸鱼划水的小伙伴&#xff0c;请点击【摸鱼学习交流群】 引言 在现代软件开发中…

python如何打包成应用

前几天有学生问&#xff0c;开发好的python代码如何打包给对方使用&#xff1f;对方没有python的安装执行环境。 python是一个强大的编程开发工具&#xff0c;它不仅仅是做一些命令行或脚本运行工具&#xff0c;还可以开发桌面、web等应用。 本文就介绍使用pyinstall如何把py…

GIS前端编程-地理事件动态模拟

GIS前端编程-地理事件动态模拟 动画特效功能图形闪烁要素轨迹移动 动画特效功能 目前&#xff0c;GIS应用除了涉及地理位置信息&#xff0c;还要结合时间维度&#xff0c;这样才能更加真实地模拟现实世界的事物。因此在实际项目应用中&#xff0c;静态的&#xff08;位置固定不…

Redis混合模式持久化原理

前言 前面文章中我们也介绍过Redis的持久化方式有两种&#xff1a;rdb持久化和aof持久化&#xff0c;具体详情可查看之前文章redis持久化。rdb持久化还是aof持久化它们都有各自的缺点。 rdb和aof缺点 rdb持久化&#xff1a;由于是定期对内存数据快照进行持久化&#xff0c;因此…

【智能家居-大模型】行业专题报告:ChatGPT等大模型催化智能家居行业发展

&#xff08;报告出品方/作者&#xff1a;华安证券&#xff0c;马远方&#xff09; 1 智能家居&#xff1a;ChatGPT 等大模型为行业发展带来新机遇 1.1 现状&#xff1a;智能家居产品的用户体验&#xff08;交互能力、智能化水 平&#xff09;及安全性待提升 智能家居&#…

编程获取图像中的圆半径

版权声明&#xff1a;本文为博主原创文章&#xff0c;转载请在显著位置标明本文出处以及作者网名&#xff0c;未经作者允许不得用于商业目的。 即将推出EmguCV的教程&#xff0c;请大家还稍作等待。 之前网友咨询如何获得图像中圆形的半径&#xff0c;其中有两个十字作为标定…

如何实现一个简单的深度优先搜索(DFS)算法?

聚沙成塔每天进步一点点 ⭐ 专栏简介⭐ 实现深度优先搜索⭐ 写在最后 ⭐ 专栏简介 前端入门之旅&#xff1a;探索Web开发的奇妙世界 记得点击上方或者右侧链接订阅本专栏哦 几何带你启航前端之旅 欢迎来到前端入门之旅&#xff01;这个专栏是为那些对Web开发感兴趣、刚刚踏入前…

Qt Quick 之 QML 与 C++ 混合编程详解

Qt Quick 之 QML 与 C 混合编程详解 一、Qt Quick 之 QML 与 C 混合编程详解在 QML 中使用 C 类和对象实现可以导出的 C 类Q_INVOKABLE 宏Q_ENUMSQ_PROPERTY注册一个 QML 中可用的类型注册 QML 类型在 QML 中导入 C 注册的类型完整的 colorMaker 实例导出一个 C 对象为 QML 的属…

伴随矩阵与可逆矩阵

目录 伴随矩阵的概念与公式 可逆矩阵的概念与定理 逆矩阵的运算性质 伴随矩阵的概念与公式 伴随矩阵是一个与给定矩阵相关的矩阵&#xff0c;它的元素是给定矩阵的代数余子式。 给定一个nn的方阵A&#xff0c;其元素为aij&#xff0c;则A的伴随矩阵adj(A)是一个nn的方阵&…

EDI 许可证申请对网站有哪些要求?

EDI 许可证申请对网站有哪些要求&#xff1f; 1、电商类平台&#xff1b; 2、二手交易类平台&#xff1b; 3、外卖类平台&#xff1b; 4、票务交易类平台&#xff1b; 5、智能数据处理平台。 ​网站如果是上述类型&#xff0c;那就要办理EDI许可证&#xff0c;但EDI许可证…

北航投资携核心医疗获2023年度十佳投资案例

近日&#xff0c;全球PE论坛联合财新数据发布了2022-2023年度中国PE/VC行业评选结果&#xff0c;北航投资携核心医疗荣获2022-2023年度中国PE/VC十佳投资案例大奖。 经过7年的发展&#xff0c;北航投资的各项业务正密集地进入收获期&#xff0c;业务增长飞轮持续加速&#xff0…