drools的类型声明(Type declarations)
一、背景
在我们编写drl
规则的时候,有些时候需要自己声明一些类,用于辅助之后的规则运行,如果需要用到的类还需要在java
中预先声明出来,这样就不灵活了,那么是否可以在drl
文件中声明一个类呢?可以使用drools的 Type declaration
来实现。
二、前置知识
1、Type declaration语法结构
2、java代码中获取drl声明的类型
1、非枚举类型
KieBase kieBase = kieContainer.getKieBase("type-kabse");
// 规则文件的包名 声明的类型名
FactType productOrderFactType = kieBase.getFactType("rules", "ProductOrder");
Object instance = productOrderFactType.newInstance();
productOrderFactType.set(instance, "orderId", 20220517121212001L);
2、获取枚举类型的值
需要通过反射来获取到。
KieBase kieBase = kieContainer.getKieBase("type-kabse");
// 此处的FactType的真实类型是EnumClassDefinition,可以获取到枚举中构造方法的参数的值
FactType orderStatusFactType = kieBase.getFactType("rules", "OrderStatus");
// 获取drools中枚举的值
Class<?> factClass = orderStatusFactType.getFactClass();
Method method = factClass.getMethod("valueOf", String.class);
Object pay = method.invoke(null, "PAY");
注意:
如果上方的代码看不懂,则接着往下看。
三、需求
1、在drl文件中声明一个枚举类型。
2、在drl文件中声明一个类。
3、在drl文件中声明一个类并完成继承操作。
4、编写rule
并使用我们自定义的type。
5、java中给在drl文件中声明的type赋值,包括类和枚举类型。
四、实现
1、在drl文件中声明一个枚举类型
// 声明一个枚举类型
declare enum OrderStatus
CREATED(0, "新创建"),
PAY(1, "已支付"),
RECEIVED(2, "已接收");
status: Integer;
desc: String;
end
语法结构: declare enum 枚举名字 end
2、在drl文件中声明一个类
// 声明一个类
declare BaseOrder
orderId: Long // 订单id
createdTime: Date // 时间
item: ProductItem // java中定义的类
orderStatus: OrderStatus // 上方定义的枚举类型
end
这个类中的每个属性都有一个类型
,这个类型可以是已经存在的fact,也可以是任何有效的Java类型。
3、在drl文件中声明一个类并完成继承操作
// 实现继承操作
declare ProductOrder extends BaseOrder
userId: Long // 下单用户的id
end
使用extends
来完成继承操作。
4、编写rule并使用我们自定义的type
// 定义一个规则,规则内存中存在ProductOrder并且 orderStatus是已支付userId==1001
rule "rule_type"
no-loop true
when
$order: ProductOrder(userId == 1001 && orderStatus == OrderStatus.PAY)
then
String createdTime = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss")
.format($order.getCreatedTime());
System.out.println("用户["+ $order.getUserId() +"]在["+ createdTime +"]购买的["+ $order.getItem().getItemName() +"]已完成付款");
modify($order){
setOrderStatus(OrderStatus.RECEIVED)
}
end
解释:
1、如果规则内存中存在ProductOrder
对象,并且userId的值是1001
,orderStatus的值是PAY
则该规则被激活了。
2、当该规则激活时,修改订单的状态为RECEIVED
,在java代码中获取修改后的值。
5、java中给在drl文件中声明的type赋值
@Slf4j
public class DroolsTypeDeclareApplication {
public static void main(String[] args) throws InstantiationException, IllegalAccessException, NoSuchMethodException, InvocationTargetException {
KieServices kieServices = KieServices.get();
KieContainer kieContainer = kieServices.getKieClasspathContainer();
KieSession kieSession = kieContainer.newKieSession("type-ksession");
kieSession.addEventListener(new DebugRuleRuntimeEventListener());
kieSession.addEventListener(new DebugAgendaEventListener());
kieSession.addEventListener(new DebugProcessEventListener());
KieBase kieBase = kieContainer.getKieBase("type-kabse");
FactType productOrderFactType = kieBase.getFactType("rules", "ProductOrder");
FactType orderStatusFactType = kieBase.getFactType("rules", "OrderStatus");
// 获取drools中枚举的值
Class<?> factClass = orderStatusFactType.getFactClass();
Method method = factClass.getMethod("valueOf", String.class);
Object pay = method.invoke(null, "PAY");
Object instance = productOrderFactType.newInstance();
ProductItem item = new ProductItem();
item.setItemName("iphone 13");
productOrderFactType.set(instance, "orderId", 20220517121212001L);
productOrderFactType.set(instance, "createdTime", new Date());
productOrderFactType.set(instance, "item", item);
productOrderFactType.set(instance, "orderStatus", pay);
productOrderFactType.set(instance, "userId", 1001L);
kieSession.insert(instance);
kieSession.fireAllRules();
Object orderStatus = productOrderFactType.get(instance, "orderStatus");
log.info("获取rule中修改之后的枚举字段的值:[{}]", orderStatus);
kieSession.dispose();
}
}
注意:
1、在java中获取到drl文件中声明的类型,需要使用 kieBase.getFactType
来获取。
2、如果需要获取到drl文件中申明的枚举类型的值,可以通过反射来获取。
6、运行上方的代码
用户[1001]在[2022-05-17 11:42:27]购买的[iphone 13]已完成付款
11:42:27.724 [main] INFO com.huan.drools.querys.DroolsTypeDeclareApplication - 获取rule中修改之后的枚举字段的值:[RECEIVED]
可以看到规则执行了,并且java中也获取到了工作内存中修改后的值。
五、完整代码
https://gitee.com/huan1993/spring-cloud-parent/tree/master/drools/drools-drl-type-declarations
六、参考链接
drools的类型声明(Type declarations)的更多相关文章
- Go语言规格说明书 之 类型声明(Type declarations)
go version go1.11 windows/amd64 本文为阅读Go语言中文官网的规则说明书(https://golang.google.cn/ref/spec)而做的笔记,完整的介绍Go语 ...
- [Effective Modern C++] Item 5. Prefer auto to explicit type declarations - 相对显式类型声明,更倾向使用auto
条款5 相对显式类型声明,更倾向使用auto 基础知识 auto能大大方便变量的定义,可以表示仅由编译器知道的类型. template<typename It> void dwim(It ...
- Return type declarations返回类型声明
PHP 7.新增了返回类型声明 http://php.net/manual/en/functions.returning-values.php 在PHP 7.1中新增了返回类型声明为void,以及类型 ...
- Effective Modern C++翻译(6)-条款5:auto比显示的类型声明要更好
在概念上说,auto关键字和它看起来一样简单,但是事实上,它要更微妙一些的.使用auto会让你在声明变量时省略掉类型,同时也会防止了手动类型声明带来的正确性和性能上的困扰:虽然按照语言预先定义 ...
- 如何阅读复杂的C类型声明
阅读复杂的C类型声明,通常采用右左法则,也就是Clockwise/Spiral Rule (顺时针/螺旋法则). 本文将首先介绍工具(cdecl)(个人比较偏好使用工具提高学习和工作效率),然后中英文 ...
- Swift编程语言学习12 ——实例方法(Instance Methods)和类型方法(Type Methods)
方法是与某些特定类型相关联的函数.类.结构体.枚举都能够定义实例方法:实例方法为给定类型的实例封装了详细的任务与功能.类.结构体.枚举也能够定义类型方法:类型方法与类型本身相关联.类型方法与 Obje ...
- 读书笔记 effective c++ Item 19 像设计类型(type)一样设计
1. 你需要重视类的设计 c++同其他面向对象编程语言一样,定义了一个新的类就相当于定义了一个新的类型(type),因此作为一个c++开发人员,大量时间会被花费在扩张你的类型系统上面.这意味着你不仅仅 ...
- 父类通过泛型获得子类Class类型 以及Type体系
1.背景介绍 在实现SSH框架中,DAO层向数据库持久化的过程中,因为大部分保存对象的方法都会调用到sava():所有索性就把save delete update select 方法进行封装到父类中, ...
- item 5: 比起显式的类型声明,更偏爱auto
本文翻译自modern effective C++,由于水平有限,故无法保证翻译完全正确,欢迎指出错误.谢谢! 博客已经迁移到这里啦 啊,简单愉快的代码: int x; 等等,讨厌!我忘了初始化x,所 ...
随机推荐
- 通过pink构造简易部署脚本
安装git https://www.cnblogs.com/youxiu326/p/10540753.html 安装maven https://www.cnblogs.com/youxi ...
- java中方法重载是什么, 实际中到底有什么意义, 用处?请举例
7.3 方法重载(overload) 当几个方法有相同的方法名,但参数个数不同或参数类型不同时,就涉及方法重载 方法重载有什么意义呢?在公司里编程,有时候一个方法名,要用到很多次,而且每次跟每次的参 ...
- Java连接数据库报错:com.mysql.cj.jdbc.exceptions.CommunicationsException: Communications link failure
解决方案 连接Mysql报错 The last packet sent successfully to the server was 0 milliseconds ago. The driver ha ...
- 第一阶段:Java基础之数组
注意点: @Java语言是把数组当作一个"对象"来看待的 @把数组分为两部分看,一部分是数组的引用,放置在栈内存中,一部分是数组对象,放置在堆内存中 @数组的引用可以指向任何有效的 ...
- re模块补充与其他模块介绍
注:昨日写了re单个模块几个重要的点需要补充 一.re模块补充 1.findall独有的优先级别展示 res = re.findall('abc', 'abcabcabcabc') print(res ...
- 【面试普通人VS高手】Kafka的零拷贝原理?
最近一个学员去滴滴面试,在第二面的时候遇到了这个问题: "请你简单说一下Kafka的零拷贝原理" 然后那个学员努力在大脑里检索了很久,没有回答上来. 那么今天,我们基于这个问题来看 ...
- toggleClass() 把本来的有的类名去掉 本来没有的 加上
连续点击按钮可以交替颜色,就是改变class
- nodejs的tream(流)解析与模拟文件读写流源码实现
什么是流? 可读流于可写流 双工流于转换流 背压机制与文件流模拟实现 一.什么是流? 关于流的概念早在1964年就有记录被提出了,简单的说"流"就是控制数据传输过程的程序,比如在那 ...
- Service vs Factory vs provider的迷惑
刚开始我很迷惑的,但是经过一段时间的项目,还有看大漠老师的东西,似乎明白了,他们的区别也就是 一个人喜欢吃面还是吃饭或者肯德基区别.目的就是填饱肚子! 以下是它们在AngularJS源代码中的定义: ...
- Visual Studio2019 F5调试程序时选择文件后调试控制台进程关闭问题
问题:Visual Studio2019 F5调试程序时选择文件后调试控制台进程关闭问题 解决方案: 修改Visual Studio 配置项 [工具]-[选项]-[项目和解决方案]-[Web项目]-[ ...