我们知道在drools中是存在工作内存的,我们的Fact对象会加入到工作内存中,同时我们自己也可以在drl文件中使用insert/modify/update/delete等方法,修改工作内存中对象的,那么我们怎么查询修改之后的工作内存的值呢?而drools的query可以帮助我们实现这个功能。
二、需求1、无参数query的使用 2、有参数query的使用 3、java代码中openLiveQuery的使用 4、rule中使用query
三、前置需求1、query的语法结构query queryName(参数列表)end注意事项: ?
query的名字在同一个KIE base的所有包中必须要唯一,一般情况下我们全局唯一即可。
query没有when和then的部分
2、java中如何获取query的结果1、通过getQueryResults获取
QueryResults queryResults = kieSession.getQueryResults("query的名字",可选参数类表);通过这种方式getQueryResults获取到的结果只会获取一次,如果工作内存中的数据发生了变化,则不会自动感知到。
2、通过openLiveQuery获取
kieSession.openLiveQuery("query的名字", new Object[]{可选参数}, new ViewChangedEventListener() {@Overridepublic void rowInserted(Row row) {}@Overridepublic void rowDeleted(Row row) { }@Overridepublic void rowUpdated(Row row) {}});通过这种方式openLiveQuery是可以实时获取到结果的,当工作内存中的数据发生变化,这个地方是可以感知到的。
四、实现此处只列出部分核心代码,一些无关的代码不列出。
1、无参数query的使用1、drl文件编写// 不带参数的查询query "query01"// 注意这个地方的 $p,java代码中需要用到$p: Person(age < 18)end2、java文件编写// 不带参数的query查询QueryResults queryResults = kieSession.getQueryResults("query01");queryResults.iterator().forEachRemaining(row -> {// 那么这个地方的 $p 是怎么来的呢?其实是我们自己编写的drl query中写的Person person = (Person) row.get("$p");log.info("query01从工作内存中获取的query: {}", person);});2、有参数query的使用1、drl文件编写// 带参数的查询query query02(Integer $age)$p: Person(age < $age)end2、java文件编写// 不带参数的query查询// 带参数的query查询queryResults = kieSession.getQueryResults("query02", 20);queryResults.iterator().forEachRemaining(row -> {Person person = (Person) row.get("$p");log.info("query02从工作内存中获取的query: {}", person);});3、java代码中openLiveQuery的使用1、drl文件编写// 带参数的查询-查询工作内存Person对象的age的值小于外部传递进来的$age值query query02(Integer $age)$p: Person(age < $age)end// 定义一个规则,当规则内存中的Person的age小于18时,直接年龄+1rule "rule_test_live_query_in_java"no-loop truewhen$p: Person($age:age < 18)thenmodify($p){// 此处修改了工作内存中age对象的值setAge($p.getAge() + 1)}System.out.println("更新来规则内存中Person["+$p.getName()+"]的age:["+$p.getAge()+"]值");end解释: 1、定义查询query02查询工作内存中的对象。 2、rule_test_live_query_in_java里面存在一个 modify($p) 这个操作会导致更新工作内存中对象的值。 3、no-loop true表达的是当前规则是否可以多次执行,就我们定义的这个规则,如果修改后的age<18那么可能还会导致规则的重新出发,加了no-loop true则只会触发一次。
2、java文件编写public static void main(String[] args) {KieServices kieServices = KieServices.get();KieContainer kieContainer = kieServices.getKieClasspathContainer();KieSession kieSession = kieContainer.newKieSession("query-ksession");kieSession.addEventListener(new DebugRuleRuntimeEventListener());kieSession.addEventListener(new DebugAgendaEventListener());kieSession.addEventListener(new DebugProcessEventListener());// 实时查询kieSession.openLiveQuery("query02", new Object[]{20}, new ViewChangedEventListener() {@Overridepublic void rowInserted(Row row) {Person person = (Person) row.get("$p");log.info("实时查询-query02向工作内存中插入Person: {}", person);}@Overridepublic void rowDeleted(Row row) {Person person = (Person) row.get("$p");log.info("实时查询-query02向工作内存中删除Person: {}", person);}@Overridepublic void rowUpdated(Row row) {Person person = (Person) row.get("$p");log.info("实时查询-query02向工作内存中更新Person: {}", person);}});Person person1 = new Person("张三", 16);kieSession.insert(person1);kieSession.fireAllRules();kieSession.dispose();}解释: 1、此处先使用了openLiveQuery查询。 2、让后向工作内存中insert(person1),并且触发了所有的规则fireAllRules。
3、输出结果10:08:54.415 [main] INFO com.huan.drools.querys.DroolsLiveQueryApplication - 实时查询-query02向工作内存中插入Person: Person(name=张三, age=16)更新来规则内存中Person[张三]的age:[17]值10:08:54.420 [main] INFO com.huan.drools.querys.DroolsLiveQueryApplication - 实时查询-query02向工作内存中更新Person: Person(name=张三, age=17)可以看到,openLiveQuery实时查询到了工作内存中变更的对象。
4、rule中使用querydrl文件编写
QueryResults queryResults = kieSession.getQueryResults("query的名字",可选参数类表);0如果出现了如下异常Query's must use positional or bindings, not field constraints: "张" : [Rule name='rule_person_name_starts_with'],这个是因为我们在rule中调用query时,参数没有以;结尾。正确用法personNameStartsWith("张";)
?personNameStartsWith("张";) 和 personNameStartsWith("张";)是不一样的。The ? symbol means the query is pull only, once the results are returned you will not receive further results as the underlying data changes
五、完整代码https://gitee.com/huan1993/spring-cloud-parent/tree/master/drools/drools-drl-query
六、参考链接1、https://docs.drools.org/7.69.0.Final/drools-docs/html_single/index.html#drl-queries-con_drl-rules ?
原文:https://juejin.cn/post/7098275219344900109logo设计
创造品牌价值
¥500元起
APP开发
量身定制,源码交付
¥2000元起
商标注册
一个好品牌从商标开始
¥1480元起
公司注册
注册公司全程代办
¥0元起
查
看
更
多
drools中query的使用
1、无参数query的使用1、drl文件编写\/\/ 不带参数的查询query "query01"\/\/ 注意这个地方的 $p,java代码中需要用到$p: Person(age < 18)end 2、java文件编写\/\/ 不带参数的query查询QueryResults queryResults = kieSession.getQueryResults("query01");queryResults.iterator().forEachRemaining(row...
规则引擎Drools在贷后催收业务中的应用
2.2 规则2.2.1 规则文件解析DRL(Drools规则语言)定义业务规则,包含package、import、function、global、query、rule等元素,同时支持Excel格式。2.2.2 使用案例通过DRL文件定义查询,搜索与规则相关的事实。在DRL文件中添加查询定义,应用程序代码中获取匹配结果。2.3 工程引入2.3.1 配置文件引入通过k...
Drools规则引擎
使用匹配器(Pattern Matcher)将规则库中的规则(rule)和数据(fact)匹配,匹配成功的放入到议程(Agenda)中 如果执行规则存在冲突,即同时激活了多个规则,将冲突的规则放入冲突集合(冲突是同时匹配了多条规则,不需要自己处理,drools会自动处理) 解决冲突,将激活的规则按顺序放入议程(Agenda) 执行议程(Agenda)中的规则,重复...
drools的类型声明(Type declarations)
6、运行上方的代码用户[1001]在[2022-05-17 11:42:27]购买的[iphone 13]已完成付款11:42:27.724 [main] INFO com.huan.drools.querys.DroolsTypeDeclareApplication - 获取rule中修改之后的枚举字段的值:[RECEIVED]可以看到规则执行了,并且java中也获取到了工作内存中修改后的值。 ?五、完整代码...
springboot集成大全(springboot集成camunda)
Drools集成SpringBoot 为了更好的在项目中使用Drools, 需要把Drools集成到SpringBoot, 下面介绍集成的方法, 并且开发简单的Demo和测试用例。 pom.xml工程信息: 引入spring-boot-starter-web作为Web工程,对外提供Rest服务, 引入spring-boot-starter-log4j2日志框架,打印测试匹配结果, 引入spring-boot-starter-test测试框架...
有什么比较好的开源的工作流引擎吗?
jBPM由JBoss公司开发,最高版本为7.61.0.Final。从jBPM5开始与之前产品不同,基于Drools Flow,但在国内市场使用较少。jBPM4由Tom Baeyens创建,后加入Alfresco,推出基于jBPM4的开源工作流系统Activiti。osworkflow是一个轻量级流程引擎,基于状态机机制,支持步骤、条件、循环、分支等,但不支持会签、跳转、...
springboot集成大全(springboot集成camunda)
在上面PersonRuleController中需要用到KieContainer, 这个必须在Spring中先初始化才能使用, 相关功能由DroolsAutoConfiguration.java提供: 在DroolsAutoConfiguration中指定了drl规则文件 所在目录rules\/com\/ai\/prd\/, 在src\/main\/resources\/rules\/com\/ai\/prd\/目录下新建文件 ai-rules.drl: 规则1匹配名字为bob的人,并且调...