一、背景
咱们晓得在 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() {
@Override
public void rowInserted(Row row) {}
@Override
public void rowDeleted(Row row) { }
@Override
public void rowUpdated(Row row) {}});
通过这种形式 openLiveQuery
是能够实时获取到后果的,当工作内存中的数据发生变化,这个中央是能够感知到的。
四、实现
此处只列出局部外围代码,一些无关的代码不列出。
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 -> {
// 那么这个中央的 $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)
end
2、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 时,间接年龄 +1
rule "rule_test_live_query_in_java"
no-loop true
when
$p: Person($age:age < 18)
then
modify($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() {
@Override
public void rowInserted(Row row) {Person person = (Person) row.get("$p");
log.info("实时查问 -query02 向工作内存中插入 Person: {}", person);
}
@Override
public void rowDeleted(Row row) {Person person = (Person) row.get("$p");
log.info("实时查问 -query02 向工作内存中删除 Person: {}", person);
}
@Override
public 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 中应用 query
drl
文件编写
// 定义一个查问,Person#name 须要以 $prefix 结尾
query personNameStartsWith(String $prefix)
Person(name.startsWith($prefix))
end
rule "rule_person_name_starts_with"
when
$p: Person($age:age < 18)
personNameStartsWith("张";) // 此处多个参数应用 , 宰割,并且最初必须以 ; 结尾
then
System.out.println("在 rule 中应用 query");
end
如果呈现了如下异样 `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