drools高级语法

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

关键字

描述

package

包名,只限于逻辑上的管理,同一个包名下的查询或者函数可以直接调用

import

用于导入类或者静态方法

global

全局变量

function

自定义函数

query

查询

rule end

规则体

本章节我们就来学习其中的几个关键字。

1 global全局变量

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

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

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

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

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

下面我们通过代码进行验证:

第一步:创建UserService类

package com.itheima.drools.service;public class UserService {
    public void save(){
        System.out.println("UserService.save()...");
    }
}

第二步:编写规则文件/resources/rules/global.drl

package testglobal
/*
    此规则文件用于测试global全局变量
*/global java.lang.Integer count //定义一个包装类型的全局变量
global com.itheima.drools.service.UserService userService //定义一个JavaBean类型的全局变量
global java.util.List gList //定义一个集合类型的全局变量rule "rule_global_1"when
    then
        count += 10; //全局变量计算,只对当前规则有效,其他规则不受影响
        userService.save();//调用全局变量的方法
        gList.add("itcast");//向集合类型的全局变量中添加元素,Java代码和所有规则都受影响
        gList.add("itheima");
        System.out.println("count=" + count);
        System.out.println("gList.size=" + gList.size());
endrule "rule_global_2"whenthen
        userService.save();
        System.out.println("count=" + count);
        System.out.println("gList.size=" + gList.size());
end

第三步:编写单元测试

KieServices kieServices = KieServices.Factory.get();
KieContainer kieClasspathContainer = kieServices.getKieClasspathContainer();
KieSession kieSession = kieClasspathContainer.newKieSession();//设置全局变量,名称和类型必须和规则文件中定义的全局变量名称对应
kieSession.setGlobal("userService",new UserService());
kieSession.setGlobal("count",5);
List list = new ArrayList();//size为0
kieSession.setGlobal("gList",list);kieSession.fireAllRules();
kieSession.dispose();//因为在规则中为全局变量添加了两个元素,所以现在的size为2
System.out.println(list.size());

2 query查询

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

query 查询的名称(可选参数)
    LHS
end

具体操作步骤:

第一步:编写规则文件/resources/rules/query.drl

package testquery
import com.itheima.drools.entity.Student
/*
    此规则文件用于测试query查询
*///不带参数的查询
//当前query用于查询Working Memory中age>10的Student对象
query "query_1"
    $student:Student(age > 10)
end//带有参数的查询
//当前query用于查询Working Memory中age>10同时name需要和传递的参数name相同的Student对象
query "query_2"(String sname)
    $student:Student(age > 20 && name == sname)
end

第二步:编写单元测试

KieServices kieServices = KieServices.Factory.get();
KieContainer kieClasspathContainer = kieServices.getKieClasspathContainer();
KieSession kieSession = kieClasspathContainer.newKieSession();Student student1 = new Student();
student1.setName("张三");
student1.setAge(12);Student student2 = new Student();
student2.setName("李四");
student2.setAge(8);Student student3 = new Student();
student3.setName("王五");
student3.setAge(22);//将对象插入Working Memory中
kieSession.insert(student1);
kieSession.insert(student2);
kieSession.insert(student3);//调用规则文件中的查询
QueryResults results1 = kieSession.getQueryResults("query_1");
int size = results1.size();
System.out.println("size=" + size);
for (QueryResultsRow row : results1) {Student student = (Student) row.get("$student");
    System.out.println(student);
}//调用规则文件中的查询
QueryResults results2 = kieSession.getQueryResults("query_2","王五");
size = results2.size();
System.out.println("size=" + size);
for (QueryResultsRow row : results2) {Student student = (Student) row.get("$student");
    System.out.println(student);
}
//kieSession.fireAllRules();
kieSession.dispose();

3 function函数

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

函数定义的语法结构如下:

function 返回值类型 函数名(可选参数){//逻辑代码
}

具体操作步骤:

第一步:编写规则文件/resources/rules/function.drl

package testfunction
import com.itheima.drools.entity.Student
/*
    此规则文件用于测试function函数
*///定义一个函数
function String sayHello(String name){return "hello " + name;
}rule "rule_function_1"when
        $student:Student(name != null)
    then//调用上面定义的函数String ret = sayHello($student.getName());
        System.out.println(ret);
end

第二步:编写单元测试

KieServices kieServices = KieServices.Factory.get();
KieContainer kieClasspathContainer = kieServices.getKieClasspathContainer();
KieSession kieSession = kieClasspathContainer.newKieSession();Student student = new Student();
student.setName("小明");kieSession.insert(student);kieSession.fireAllRules();
kieSession.dispose();

4 LHS加强

前面我们已经知道了在规则体中的LHS部分是介于when和then之间的部分,主要用于模式匹配,只有匹配结果为true时,才会触发RHS部分的执行。本章节我们会针对LHS部分学习几个新的用法。

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 ("张三","李四","王五"))

4.2 条件元素eval

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

eval(表达式)

举例:

eval(true)
eval(false)
eval(1 == 1)

4.3 条件元素not

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

not Object(可选属性约束)

举例:

not Student()
not Student(age < 10)

4.4 条件元素exists

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

exists Object(可选属性约束)

举例:

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

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

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

例如:

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

rule "使用exists的规则"whenexists Student()then
        System.out.println("规则:使用exists的规则触发");
endrule "没有使用exists的规则"whenStudent()then
        System.out.println("规则:没有使用exists的规则触发");
end

Java代码:

kieSession.insert(new Student());
kieSession.insert(new Student());
kieSession.fireAllRules();

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

4.5 规则继承

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

例如:

rule "rule_1"whenStudent(age > 10)then
        System.out.println("规则:rule_1触发");
endrule "rule_2" extends "rule_1" //继承上面的规则when/*
        此处的条件虽然只写了一个,但是从上面的规则继承了一个条件,
        所以当前规则存在两个条件,即Student(age < 20)和Student(age > 10)
        */Student(age < 20) then
        System.out.println("规则:rule_2触发");
end

5 RHS加强

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

在RHS部分Drools为我们提供了一个内置对象,名称就是drools。本小节我们来介绍几个drools对象提供的方法。

5.1 halt

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

package testhalt
rule "rule_halt_1"whenthen
        System.out.println("规则:rule_halt_1触发");
        drools.halt();//立即终止后面所有规则执行
end//当前规则并不会触发,因为上面的规则调用了halt方法导致后面所有规则都不会执行
rule "rule_halt_2"whenthen
        System.out.println("规则:rule_halt_2触发");
end

5.2 getWorkingMemory

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

package testgetWorkingMemory
rule "rule_getWorkingMemory"whenthen
        System.out.println(drools.getWorkingMemory());
end

5.3 getRule

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

package testgetRule
rule "rule_getRule"whenthen
        System.out.println(drools.getRule());
end

6 规则文件编码规范

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

  • 所有的规则文件(.drl)应统一放在一个规定的文件夹中,如:/rules文件夹
  • 书写的每个规则应尽量加上注释。注释要清晰明了,言简意赅
  • 同一类型的对象尽量放在一个规则文件中,如所有Student类型的对象尽量放在一个规则文件中
  • 规则结果部分(RHS)尽量不要有条件语句,如if(…),尽量不要有复杂的逻辑和深层次的嵌套语句
  • 每个规则最好都加上salience属性,明确执行顺序
  • Drools默认dialect为”Java”,尽量避免使用dialect “mvel”

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

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

相关文章

Win32 Socket 使用

库说明 Win32 进行网络编程需要使用到 ws2_32.lib 库&#xff0c;它是 Windows Sockets 2 (Winsock2) 的库文件&#xff0c;其主要头文件为winsock2.h。如果使用 Windows.h 头文件则默认包含 winsock.h&#xff0c;他会和 winsock2.h 冲突。可以通过在包含 Windows.h 之前定义…

数据压缩(哈夫曼编码)

【问题描述】在数据压缩问题中&#xff0c;需要将数据文件转换成由二进制字符0、1组成的二进制串&#xff0c;称之为编码&#xff0c;已知待压缩的数据中包含若干字母&#xff08;A-Z&#xff09;&#xff0c;为获得更好的空间效率&#xff0c;请设计有效的用于数据压缩的二进制…

MLX vs MPS vs CUDA:苹果新机器学习框架的基准测试

如果你是一个Mac用户和一个深度学习爱好者&#xff0c;你可能希望在某些时候Mac可以处理一些重型模型。苹果刚刚发布了MLX&#xff0c;一个在苹果芯片上高效运行机器学习模型的框架。 最近在PyTorch 1.12中引入MPS后端已经是一个大胆的步骤&#xff0c;但随着MLX的宣布&#x…

在Excel中,如何简单快速地删除重复项,这里提供详细步骤

当你在Microsoft Excel中使用电子表格时&#xff0c;意外地复制了行&#xff0c;或者如果你正在制作其他几个电子表格的合成电子表格&#xff0c;你将遇到需要删除的重复行。这可能是一项非常无脑、重复、耗时的任务&#xff0c;但有几个技巧可以让它变得更简单。 删除重复项 …

Android Canvas画布saveLayer与对应restoreToCount,Kotlin

Android Canvas画布saveLayer与对应restoreToCount&#xff0c;Kotlin private fun mydraw() {val originBmp BitmapFactory.decodeResource(resources, R.mipmap.pic).copy(Bitmap.Config.ARGB_8888, true)val newBmp Bitmap.createBitmap(originBmp.width, originBmp.heigh…

【Win10安装Qt6.3】安装教程_保姆级

前言 Windows系统安装Qt4及Qt5.12之前版本和安装Qt.12之后及Qt6方法是不同的 &#xff1b;因为之前的版本提供的有安装包&#xff0c;直接一路点击Next就Ok了。但Qt5.12版本之后&#xff0c;Qt公司就不再提供安装包了&#xff0c;不论是社区版&#xff0c;专业版等&#xff0c…

并发控制工具类CountDownLatch、CyclicBarrier、Semaphore

并发控制工具类CountDownLatch、CyclicBarrier、Semaphore 1.CountDownLatch 可以使一个或多个线程等待其他线程各自执行完毕后再执行。 CountDownLatch 是多线程控制的一种工具&#xff0c;它被称为 门阀、 计数器或者闭锁。这个工具经常用来用来协调多个线程之间的同步&…

项目从vue2 升级vue3,项目大迁移 ,UI组件库更换

目录 背景描述 开发准备 第一步&#xff1a;升级环境 第二步&#xff1a;划分功能迁移顺序 第三步&#xff1a;详细了解需要迁移的业务页面 第四步&#xff1a;项目的一些配置的准备 详细开发流程 总结/分析&#xff1a; 背景描述 之前的版本&#xff1a;vue 2.6.8 i…

【PHY6222】绑定详解

1.函数详解 bStatus_t GAPBondMgr_SetParameter( uint16 param, uint8 len, void* pValue ) 设置绑定参数。 bStatus_t GAPBondMgr_GetParameter( uint16 param, void* pValue ) 获取绑定参数。 param&#xff1a; GAPBOND_PAIRING_MODE&#xff0c;配对模式&#xff0c;…

【postgres】8、Range 类型

文章目录 8.17 Range 类型8.17.1 内置类型8.17.2 示例8.17.3 开闭区间8.17.4 无穷区间 https://www.postgresql.org/docs/current/rangetypes.html 8.17 Range 类型 Range 类型&#xff0c;可以描述一个数据区间&#xff0c;有明确的子类型&#xff0c;而且子类型应该能被排序…

计算机网络——数据链路层(三)

前言: 前面我们已经对计算机网络的物理层有了一个大概的了解&#xff0c;今天我们学习的是物理层服务的上一层数据链路层&#xff0c;位于物理层和网络层之间。数据链路层在物理层提供的服务的基础上向网络层提供服务&#xff0c;其最基本的服务是将源自物理层来的数据可靠地传…

Mac使用Vmware Fusion虚拟机配置静态ip地址

一、设置虚拟机的网络为NAT 二、修改虚拟机的网络适配器网络 1、查看虚拟机的网卡 cd /etc/sysconfig/network-scripts#有些系统显示的是ens33&#xff0c;ens160等等 #不同的系统和版本&#xff0c;都会有所不同 #Centos8中默认是ens160,在RedHat/Centos7则为ens33 2、查看网…

Java语法---使用sort进行排序

目录 一、升序 二、降序 &#xff08;1&#xff09;类实现接口 &#xff08;2&#xff09;匿名内部类 三、自定义排序规则 四、集合中的sort排序 &#xff08;1&#xff09;升序 &#xff08;2&#xff09;降序 &#xff08;3&#xff09;自定义排序 一、升序 升序排…

如何用Java编写一个简易抽奖程序

下面是一个简易的 Java 抽奖程序的示例。这个程序使用 Random 类来生成随机数&#xff0c;模拟从一组参与者中抽奖的过程。 import java.util.ArrayList; import java.util.Random; import java.util.Scanner; public class SimpleLottery { public static void main(String[] …

C++内存管理和模板初阶

C/C内存分布 请看代码&#xff1a; int globalVar 1; static int staticGlobalVar 1; void Test() {static int staticVar 1;int localVar 1;int num1[10] { 1, 2, 3, 4 };char char2[] "abcd";const char* pChar3 "abcd";int* ptr1 (int*)mallo…

OpenHarmony之内核层解析~

OpenHarmony简介 技术架构 OpenHarmony整体遵从分层设计&#xff0c;从下向上依次为&#xff1a;内核层、系统服务层、框架层和应用层。系统功能按照“系统 > 子系统 > 组件”逐级展开&#xff0c;在多设备部署场景下&#xff0c;支持根据实际需求裁剪某些非必要的组件…

一周工作问题总结(2023.12.18-2023.12.22)

一周工作问题总结 1. 接口调用频率2. 汉字在数据库中占用字节问题3. Map在循环中修改自己的key与value4. Group BY5.递归同步数据6.代码移动Idea飘红 1. 接口调用频率 供应商给的接口可以每秒调用5-10次&#xff0c;那么我为了保险每秒调用5次&#xff0c;为了防止过度调用接口…

BUG记录——drawio出现“非绘图文件 (error on line 7355 at column 83: AttValue: ‘ expected)”

BUG现象 drawio出现“非绘图文件 (error on line 7355 at column 83: AttValue: ’ expected)”&#xff0c;如下图&#xff1a; 解决办法 这只是我自己摸索到的解决办法并不一定适用于所以人&#xff0c;对我是适用的。 首先用记事本打开损坏的drawio文件&#xff0c;如下 …

红黑树的C语言简单实现与代码解析

红黑树 C 语言的简单实现与代码解析 红黑树是计算机科学中一种重要的自平衡二叉搜索树。它确保了在最坏情况下&#xff0c;基本的动态集合操作&#xff08;如插入、删除和查找&#xff09;具有对数时间复杂度。在这篇博客中&#xff0c;我们将介绍一个简化的C语言红黑树实现&a…

mathtype公式章节编号

1. word每章标题后插入章节符 如果插入后显示章节符&#xff0c;需要进行隐藏 开始->样式->MTEquationSection->修改样式->字体&#xff0c;勾选隐藏 2. 设置mathtype公式编号格式 插入编号->格式化->设置格式