尚硅谷----智尚代驾项目----Day7(续)------预估乘客订单数据之Drools

Hello uu 们!感谢你们的收看,话不多说,今天开始我们的Drools之旅

Drools介绍


drools是一款由JBoss组织提供的基于Java语言开发的开源规则引擎,可以将复杂且多变的业务规则从硬编码中解放出来,以规则脚本的形式存放在文件或特定的存储介质中(例如存放在数据库中),使得业务规则的变更不需要修改项目代码、重启服务器就可以在线上环境立即生效。

drools官网地址:https://drools.org/

drools源码下载地址:https://github.com/kiegroup/drools

Drools入门案例
1.创建springboot项目

groupId:com.atguigu.drools
artifactId:drools_demo

2.引入依赖

    <parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>3.0.5</version><relativePath/> <!-- lookup parent from repository --></parent><properties><java.version>17</java.version><drools.version>8.41.0.Final</drools.version></properties><dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter</artifactId></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>${drools.version}</version></dependency><dependency><groupId>org.drools</groupId><artifactId>drools-compiler</artifactId><version>${drools.version}</version></dependency><dependency><groupId>org.drools</groupId><artifactId>drools-decisiontables</artifactId><version>${drools.version}</version></dependency><dependency><groupId>org.drools</groupId><artifactId>drools-mvel</artifactId><version>${drools.version}</version></dependency></dependencies>
3.添加Drools配置类
package com.atguigu.drools.config;import org.kie.api.KieServices;
import org.kie.api.builder.*;
import org.kie.api.runtime.KieContainer;
import org.kie.api.runtime.KieSession;
import org.kie.internal.io.ResourceFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;/*** 规则引擎配置类*/
@Configuration
public class DroolsConfig {private static final KieServices kieServices = KieServices.Factory.get();//制定规则文件的路径private static final String RULES_CUSTOMER_RULES_DRL = "rules/order.drl";@Beanpublic KieContainer kieContainer() {//获得Kie容器对象KieFileSystem kieFileSystem = kieServices.newKieFileSystem();kieFileSystem.write(ResourceFactory.newClassPathResource(RULES_CUSTOMER_RULES_DRL));KieBuilder kieBuilder = kieServices.newKieBuilder(kieFileSystem);kieBuilder.buildAll();KieModule kieModule = kieBuilder.getKieModule();KieContainer kieContainer = kieServices.newKieContainer(kieModule.getReleaseId());return kieContainer;}}

说明:

  • 定义了一个 KieContainer的Spring Bean ,KieContainer用于通过加载应用程序的/resources文件夹下的规则文件来构建规则引擎。
  • 创建KieFileSystem实例并配置规则引擎并从应用程序的资源目录加载规则的 DRL 文件。
  • 使用KieBuilder实例来构建 drools 模块。我们可以使用KieSerive单例实例来创建 KieBuilder 实例。
  • 最后,使用 KieService 创建一个 KieContainer 并将其配置为 spring bean


4.创建实体类Orde

package com.atguigu.drools.model;public class Order {private double amout;private double score;public double getAmout() {return amout;}public void setAmout(double amout) {this.amout = amout;}public double getScore() {return score;}public void setScore(double score) {this.score = score;}
}
5.order.drl

创建规则文件resources/rules/order.drl

//订单积分规则
package com.order
import com.atguigu.drools.model.Order//规则一:100元以下 不加分
rule "order_rule_1"when$order:Order(amout < 100)then$order.setScore(0);System.out.println("成功匹配到规则一:100元以下 不加分");
end//规则二:100元 - 500元 加100分
rule "order_rule_2"when$order:Order(amout >= 100 && amout < 500)then$order.setScore(100);System.out.println("成功匹配到规则二:100元 - 500元 加100分");
end//规则三:500元 - 1000元 加500分
rule "order_rule_3"when$order:Order(amout >= 500 && amout < 1000)then$order.setScore(500);System.out.println("成功匹配到规则三:500元 - 1000元 加500分");
end//规则四:1000元以上 加1000分
rule "order_rule_4"when$order:Order(amout >= 1000)then$order.setScore(1000);System.out.println("成功匹配到规则四:1000元以上 加1000分");
end

6.编写测试类

package com.atguigu.drools;import org.junit.jupiter.api.Test;
import com.atguigu.drools.model.Order;
import org.kie.api.runtime.KieContainer;
import org.kie.api.runtime.KieSession;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;@SpringBootTest
class DroolsDemosApplicationTests {@Autowiredprivate KieContainer kieContainer;@Testpublic void test(){//从Kie容器对象中获取会话对象KieSession session = kieContainer.newKieSession();//Fact对象,事实对象Order order = new Order();order.setAmout(1300);//将Order对象插入到工作内存中session.insert(order);//激活规则,由Drools框架自动进行规则匹配,如果规则匹配成功,则执行当前规则session.fireAllRules();//关闭会话session.dispose();System.out.println("订单金额:" + order.getAmout() +",添加积分:" + order.getScore());}}
  • 通过上面的入门案例我们可以发现,使用drools规则引擎主要工作就是编写规则文件,在规则文件中定义跟业务相关的业务规则。规则定义好后就需要调用drools提供的API将数据提供给规则引擎进行规则模式匹配,规则引擎会执行匹配成功的规则并将计算的结果返回给我们。
  • 可能大家会有疑问,就是我们虽然没有在代码中编写规则的判断逻辑,但是我们还是在规则文件中编写了业务规则,这跟在代码中编写规则有什么本质的区别呢?
  • 我们前面其实已经提到,使用规则引擎时业务规则可以做到动态管理。业务人员可以像管理数据一样对业务规则进行管理,比如查询、添加、更新、统计、提交业务规则等。这样就可以做到在不重启服务的情况下调整业务规则。

Drools基础语法

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

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

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

2.规则体语法结构

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

rule "ruleName"attributeswhenLHS thenRHS
end
  • rule:关键字,表示规则开始,参数为规则的唯一名称。
  • attributes:规则属性,是rule与when之间的参数,为可选项。
  • when:关键字,后面跟规则的条件部分。
  • LHS(Left Hand Side):是规则的条件部分的通用名称。它由零个或多个条件元素组成。如果LHS为空,则它将被视为始终为true的条件元素。 (左手边)
  • then:关键字,后面跟规则的结果部分。
  • RHS(Right Hand Side):是规则的后果或行动部分的通用名称。 (右手边)
  • end:关键字,表示一个规则结束。

3.注释
在drl形式的规则文件中使用注释和Java类中使用注释一致,分为单行注释和多行注释。
单行注释用"//“进行标记,多行注释以”/“开始,以”/"结束。如下示例:

//规则rule1的注释,这是一个单行注释
rule "rule1"whenthenSystem.out.println("rule1触发");
end/*
规则rule2的注释,
这是一个多行注释
*/
rule "rule2"whenthenSystem.out.println("rule2触发");
end

4.Pattern模式匹配

  • 前面我们已经知道了Drools中的匹配器可以将Rule Base中的所有规则与Working Memory中的Fact对象进行模式匹配,那么我们就需要在规则体的LHS部分定义规则并进行模式匹配。LHS部分由一个或者多个条件组成,条件又称为pattern。
  • pattern的语法结构为:绑定变量名:Object(Field约束)
  • 其中绑定变量名可以省略,通常绑定变量名的命名一般建议以$开始。如果定义了绑定变量名,就可以在规则体的RHS部分使用此绑定变量名来操作相应的Fact对象。Field约束部分是需要返回true或者false的0个或多个表达式。

例如我们的入门案例中:

//规则二:100元 - 500元 加100分
rule "order_rule_2"when$order:Order(amout >= 100 && amout < 500)then$order.setScore(100);System.out.println("成功匹配到规则二:100元 - 500元 加100分");
end

通过上面的例子我们可以知道,匹配的条件为:

  • 1、工作内存中必须存在Order这种类型的Fact对象-----类型约束
  • 2、Fact对象的amout属性值必须大于等于100------属性约束
  • 3、Fact对象的amout属性值必须小于500------属性约束
  • 以上条件必须同时满足当前规则才有可能被激活。

5.比较操作符

Drools提供的比较操作符,如下表:

前6个比较操作符和Java中的完全相同。

6.Drools内置方法

  • 规则文件的RHS部分的主要作用是通过插入,删除或修改工作内存中的Fact数据,来达到控制规则引擎执行的目的。Drools提供了一些方法可以用来操作工作内存中的数据,**操作完成后规则引擎会重新进行相关规则的匹配,**原来没有匹配成功的规则在我们修改数据完成后有可能就会匹配成功了。

6.1.update方法
update方法的作用是更新工作内存中的数据,并让相关的规则重新匹配。 (要避免死循环)

参数:

//Fact对象,事实对象
Order order = new Order();
order.setAmout(30);

规则:

//规则一:100元以下 不加分
rule "order_rule_1"when$order:Order(amout < 100)then$order.setAmout(150);update($order) //update方法用于更新Fact对象,会导致相关规则重新匹配System.out.println("成功匹配到规则一:100元以下 不加分");
end//规则二:100元 - 500元 加100分
rule "order_rule_2"when$order:Order(amout >= 100 && amout < 500)then$order.setScore(100);System.out.println("成功匹配到规则二:100元 - 500元 加100分");
end

在更新数据时需要注意防止发生死循环。

6.2.insert方法

insert方法的作用是向工作内存中插入数据,并让相关的规则重新匹配

//规则一:100元以下 不加分
rule "order_rule_1"when$order:Order(amout < 100)thenOrder order = new Order();order.setAmout(130);insert(order);      //insert方法的作用是向工作内存中插入Fact对象,会导致相关规则重新匹配System.out.println("成功匹配到规则一:100元以下 不加分");
end//规则二:100元 - 500元 加100分
rule "order_rule_2"when$order:Order(amout >= 100 && amout < 500)then$order.setScore(100);System.out.println("成功匹配到规则二:100元 - 500元 加100分");
end
6.3.retract方法

retract方法的作用是删除工作内存中的数据,并让相关的规则重新匹配

//规则一:100元以下 不加分
rule "order_rule_1"when$order:Order(amout < 100)thenretract($order)      //retract方法的作用是删除工作内存中的Fact对象,会导致相关规则重新匹配System.out.println("成功匹配到规则一:100元以下 不加分");
end
7.规则属性 attributes

前面我们已经知道了规则体的构成如下

rule "ruleName"attributeswhenLHSthenRHS
end

本章节就是针对规则体的attributes属性部分进行讲解。Drools中提供的属性如下表(部分属性):

7.1.salience属性
salience属性用于指定规则的执行优先级,取值类型为Integer。数值越大越优先执行。每个规则都有一个默认的执行顺序,如果不设置salience属性,规则体的执行顺序为由上到下。

可以通过创建规则文件salience.drl来测试salience属性,内容如下

package com.orderrule "rule_1"wheneval(true)thenSystem.out.println("规则rule_1触发");
endrule "rule_2"wheneval(true)thenSystem.out.println("规则rule_2触发");
endrule "rule_3"wheneval(true)thenSystem.out.println("规则rule_3触发");
end

通过控制台可以看到,由于以上三个规则没有设置salience属性,所以执行的顺序是按照规则文件中规则的顺序由上到下执行的。接下来我们修改一下文件内容:

package com.orderrule "rule_1"salience 9wheneval(true)thenSystem.out.println("规则rule_1触发");
endrule "rule_2"salience 10wheneval(true)thenSystem.out.println("规则rule_2触发");
endrule "rule_3"salience 8wheneval(true)thenSystem.out.println("规则rule_3触发");
end

通过控制台可以看到,规则文件执行的顺序是按照我们设置的salience值由大到小顺序执行的。
建议在编写规则时使用salience属性明确指定执行优先级。

7.2.no-loop属性
no-loop属性用于防止死循环,当规则通过update之类的函数修改了Fact对象时,可能使当前规则再次被激活从而导致死循环。取值类型为Boolean,默认值为false,测试步骤如下:

编写规则文件/resources/rules/activationgroup.drl

//订单积分规则
package com.order
import com.atguigu.drools.model.Order//规则一:100元以下 不加分
rule "order_rule_1"no-loop true         //防止陷入死循环when$order:Order(amout < 100)then$order.setScore(0);update($order)System.out.println("成功匹配到规则一:100元以下 不加分");
end

通过控制台可以看到,由于我们没有设置no-loop属性的值,所以发生了死循环。接下来设置no-loop的值为true再次测试则不会发生死循环。

8.Drools高级语法

前面章节我们已经知道了一套完整的规则文件内容构成如下:

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

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

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

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

订单Order:

package com.atguigu.drools.model;public class Order {private double amout;public double getAmout() {return amout;}public void setAmout(double amout) {this.amout = amout;}}

 积分Integral:

package com.atguigu.drools.model;public class Integral {private double score;public double getScore() {return score;}public void setScore(double score) {this.score = score;}
}

规则文件:

//订单积分规则
package com.order
import com.atguigu.drools.model.Orderglobal com.atguigu.drools.model.Integral integral;//规则一:100元以下 不加分
rule "order_rule_1"no-loop true         //防止陷入死循环when$order:Order(amout < 100)thenintegral.setScore(10);update($order)System.out.println("成功匹配到规则一:100元以下 不加分");
end

测试:

@Test
public void test1(){//从Kie容器对象中获取会话对象KieSession session = kieContainer.newKieSession();//Fact对象,事实对象Order order = new Order();order.setAmout(30);//全局变量Integral integral = new Integral();session.setGlobal("integral", integral);//将Order对象插入到工作内存中session.insert(order);//激活规则,由Drools框架自动进行规则匹配,如果规则匹配成功,则执行当前规则session.fireAllRules();//关闭会话session.dispose();System.out.println("订单金额:" + order.getAmout());System.out.println("添加积分:" + integral.getScore());
}

上午先到这啦~~~下午continue!

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

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

相关文章

Dapper 如何确保数据的安全性和防止 SQL 注入攻击?

一、什么是SQL注入攻击 SQL注入攻击是一种常见的网络攻击手段&#xff0c;它利用了应用程序中安全措施不足的问题&#xff0c;允许攻击者插入或“注入”一个或多个SQL语句到原本的查询中。这种攻击可以用于获取、篡改或删除数据库中的数据&#xff0c;甚至可以执行一些数据库管…

springboot+大数据基于数据挖掘的招聘信息可视化大屏系统【内含源码+文档+部署教程】

博主介绍&#xff1a;✌全网粉丝10W,前互联网大厂软件研发、集结硕博英豪成立工作室。专注于计算机相关专业毕业设计项目实战6年之久&#xff0c;选择我们就是选择放心、选择安心毕业✌ &#x1f345;由于篇幅限制&#xff0c;想要获取完整文章或者源码&#xff0c;或者代做&am…

项目实战:构建高效可扩展的Flask Web框架:集成Flask-SQLAlchemy、Marshmallow与日志管理

前言 在Web开发中&#xff0c;构建一个既高效又可扩展的框架是项目成功的基石。Flask作为一个轻量级的Web应用框架&#xff0c;凭借其易用性和灵活性&#xff0c;特别适合快速开发和原型设计。结合Flask-SQLAlchemy&#xff08;为Flask提供SQLAlchemy ORM支持的扩展&#xff0…

前端基础面试题·第四篇——Vue(其一)

1.v-if 和 v-show的区别 在Vue中这两个命令都用于控制元素的显示与隐藏。 (1) v-if 动态控制元素显示与隐藏&#xff0c;本质上是动态销毁或者重建元素&#xff0c;会触发浏览器重排与重绘。在切换状态时有一个局部编译/卸载的过程会适当重建或者销毁内部的事件监听、子组件。…

数据结构与算法实验9 实现无向连通图的最小生成树

文章目录 1.上机名称2.上机要求3.上机环境4.程序清单(写明运行结果及结果分析)4.1 程序清单4.1.1 头文件 Graph.h 内容如下&#xff1a;4.1.2 实现文件 Graph.cpp 内容如下&#xff1a;4.1.3 源文件 main.cpp 内容如下&#xff1a; 4.2 运行结果 5.上机体会 1.上机名称 实现无向…

如何使用Git管理项目工程

目录 安装git 注册gitee gitee注册示例 git账户配置 使用git仓库 在本地生成一个git仓库 创建文件并增加commit 命令详解 git status git add git commit git remote git push git pull git fetch git log git branch 安装git windows下安装git可以直接上git…

distinct导致sql超时

前言 昨天敲着敲着代码&#xff0c;小杨哥跑过来给我说&#xff0c;快看他们大会议室演示报错了&#xff0c;还是一堆错了。完了啊在演示的时候报错&#xff01;&#xff01;&#xff01;接下来我们分析一下是什么原因吧。 问题分析 查看日志&#xff1a; 从日志打印看明显的…

Gin框架简易搭建(3)--Grom与数据库

写在前面 项目地址 个人认为GORM 指南这个网站是相比较之下最为清晰的框架介绍 但是它在环境搭建阶段对于初学者而言不是很友好&#xff0c;尤其是使用mysql指令稍有不同&#xff0c;以及更新的方法和依赖问题都是很让人头疼的&#xff0c;而且这些报错并非逻辑上的&#xf…

用大模型优化大模型预训练数据,节省20倍计算量,实现显著性能提升!

生成式人工智能研究实验室&#xff08;GAIR&#xff0c;主页&#xff1a;https://plms.ai/&#xff09;是国内首个聚焦于生成式人工智能的高校研究组。汇聚了来自于 CMU、复旦、交大&#xff08;ACM 班、IEEE 试点班等&#xff09;等顶尖高校的年轻本硕博人才。实验室专注于三大…

大数据-150 Apache Druid 安装部署 单机启动 系统架构

点一下关注吧&#xff01;&#xff01;&#xff01;非常感谢&#xff01;&#xff01;持续更新&#xff01;&#xff01;&#xff01; 目前已经更新到了&#xff1a; Hadoop&#xff08;已更完&#xff09;HDFS&#xff08;已更完&#xff09;MapReduce&#xff08;已更完&am…

从‘盲管’到‘智网’,漫途精准构建排水管网监测方案

在城市错综复杂的基础设施网络中&#xff0c;排水管网作为城市的“血脉”&#xff0c;其高效、稳定运行直接关系到城市生活的安宁与财产的安全。面对日益频繁的雨季挑战与气候变化的不确定性&#xff0c;传统“盲管”管理模式已难以满足现代城市治理的需求。 漫途排水管网监测…

LED显示屏如何通过FMEA进行风险分析:打造无忧显示新境界

LED显示屏作为高科技产品&#xff0c;其性能受到多种因素的影响&#xff0c;包括但不限于设计缺陷、材料质量、制造工艺、使用环境等。任何环节的疏漏都可能导致显示屏出现亮度不均、色彩失真、故障频发等问题&#xff0c;进而影响用户体验和品牌形象。因此&#xff0c;通过FME…

Linux标准IO(四)-格式化I/O输入

C 库函数提供了 3 个格式化输入函数&#xff0c;包括&#xff1a;scanf()、fscanf()、sscanf()&#xff0c;其函数定义如下所示&#xff1a; #include <stdio.h> int scanf(const char *format, ...); int fscanf(FILE *stream, const char *format, ...); int sscanf(c…

Spring Web MVC课后作业

目录 1.加法计算器 2.⽤户登录 3.留⾔板 1.加法计算器 &#xff08;1&#xff09;需求分析 加法计算器功能, 对两个整数进⾏相加, 需要客⼾端提供参与计算的两个数, 服务端返回这两个整数计算 的结果。 &#xff08;2&#xff09;接⼝定义 请求路径&#xff1a; calc/sum 请…

爬取元气手机壁纸简单案例(仅用于教学,禁止任何非法获利)

爬虫常用的库 爬虫&#xff08;Web Scraping&#xff09;是一种从网页上提取数据的技术。在 Python 中&#xff0c;有许多库可以帮助实现这一目标。以下是一些常用的爬虫库&#xff0c;以及对 BeautifulSoup 的详细介绍。 常用爬虫库 1.Requests ​ a.功能&#xff1a;用于发…

spark计算引擎-架构和应用

一Spark 定义&#xff1a;Spark 是一个开源的分布式计算系统&#xff0c;它提供了一个快速且通用的集群计算平台。Spark 被设计用来处理大规模数据集&#xff0c;并且支持多种数据处理任务&#xff0c;包括批处理、交互式查询、机器学习、图形处理和流处理。 核心架构&#x…

ChatGPT Sidebar 浏览器插件配置指南

随着聊天机器人技术的不断进步&#xff0c;越来越多的人开始依赖这些强大的工具来提高工作效率、获取信息和解决问题。OpenAI 的 ChatGPT 是其中最受欢迎的聊天机器人之一。为了方便用户在浏览网页时随时与 ChatGPT 互动&#xff0c;开发者们设计了一款名为 ChatGPT Sidebar 的…

Latex——一行的划线 如何分开

代码&#xff1a; \cmidrule(r){3-4} \cmidrule(r){5-6} \cmidrule(r){7-8}效果&#xff1a; 参考文章&#xff1a; LaTeX技巧653&#xff1a;如何隔开LaTeX表格邻近\cline表格线&#xff1f;

四,MyBatis-Plus 当中的主键策略和分页插件的(详细实操使用)

四&#xff0c;MyBatis-Plus 当中的主键策略和分页插件的(详细实操使用) 文章目录 四&#xff0c;MyBatis-Plus 当中的主键策略和分页插件的(详细实操使用)1. 主键策略1.1 主键生成策略介绍 2. 准备工作&#xff1a;2.1 AUTO 策略2.2 INPUT 策略2.3 ASSIGN_ID 策略2.3.1 雪花算…

电动车、电单车入梯数据集电动车进电梯检测识别(代码+教程+数据集)

数据集介绍 共有 5347 张图像和一一对应的标注文件 标注文件格式提供了两种&#xff0c;包括VOC格式的xml文件和YOLO格式的txt文件。 标注的对象共有以下几种&#xff1a; [‘Electric-bicycle’] 标注框的数量信息如下&#xff1a;&#xff08;标注时一般是用英文标的&am…