drools规则引擎kie最佳实践
文章目录
- 监听器
- 1、AgendaEventListener 议程事件监听器
- 2、RuleRuntimeEventListener 规则运行时事件监听器
- 3、ProcessEventListener 执行流程事件监听器
- 自定义元数据
- 规则继承
- 规则多分支
- 池化session
监听器
drools支持添加三种监听器,议程事件监听器 AgendaEventListener、规则运行时事件监听器RuleRuntimeEventListener和执行流程事件监听器ProcessEventListener(以上中文名字是笔者自己起的,姑且这么叫,方便后边的理解),这三种监听器可以给开发者带来很多“后门”操作,譬如监控规则触碰情况,监控规则运行的节点个数,监控规则运行时节点数据等。
1、AgendaEventListener 议程事件监听器
public interface AgendaEventListener extends EventListener {void matchCancelled(MatchCancelledEvent var1);/*** 规则匹配成功 ***/void matchCreated(MatchCreatedEvent var1);/*** 规则匹配成功,在执行 then 之前 ***/void beforeMatchFired(BeforeMatchFiredEvent var1);/*** 规则匹配成功,在执行 then 之后 ***/void afterMatchFired(AfterMatchFiredEvent var1);void agendaGroupPopped(AgendaGroupPoppedEvent var1);void agendaGroupPushed(AgendaGroupPushedEvent var1);void beforeRuleFlowGroupActivated(RuleFlowGroupActivatedEvent var1);void afterRuleFlowGroupActivated(RuleFlowGroupActivatedEvent var1);void beforeRuleFlowGroupDeactivated(RuleFlowGroupDeactivatedEvent var1);void afterRuleFlowGroupDeactivated(RuleFlowGroupDeactivatedEvent var1);
}
这样我们就可以利用beforeMatchFired、afterMatchFired两个方法做很多事情,譬如让日志采集系统采集我们打印的规则匹配的数据做商业报表,又或者匹配上规则时触发报警动作等。
下边其他方法都是在插入Fact时触发的一些规则,有兴趣的可以自行查阅文档,或者自己动手试下
2、RuleRuntimeEventListener 规则运行时事件监听器
public interface RuleRuntimeEventListener extends EventListener {/*** Fact插入时触发 ***/void objectInserted(ObjectInsertedEvent var1);/*** Fact更新时触发 ***/void objectUpdated(ObjectUpdatedEvent var1);/*** Fact删除时触发 ***/void objectDeleted(ObjectDeletedEvent var1);
}
这个监听器就是监听我们的Fact的变化,插入、更新和删除,目前笔者在用的时候也只是打印了日志,如果你有场景在用这个监听器也可以品论区介绍一下哈
3、ProcessEventListener 执行流程事件监听器
public interface ProcessEventListener extends EventListener {void beforeProcessStarted(ProcessStartedEvent var1);void afterProcessStarted(ProcessStartedEvent var1);void beforeProcessCompleted(ProcessCompletedEvent var1);void afterProcessCompleted(ProcessCompletedEvent var1);void beforeNodeTriggered(ProcessNodeTriggeredEvent var1);void afterNodeTriggered(ProcessNodeTriggeredEvent var1);void beforeNodeLeft(ProcessNodeLeftEvent var1);void afterNodeLeft(ProcessNodeLeftEvent var1);void beforeVariableChanged(ProcessVariableChangedEvent var1);void afterVariableChanged(ProcessVariableChangedEvent var1);default void beforeSLAViolated(SLAViolatedEvent event) {}default void afterSLAViolated(SLAViolatedEvent event) {}
}
这个监听器很特殊,笔者在用的时候,同上边两个监听器一样,通过kieSession.addEventListener(ProcessEventListener)注册监听器,但就是不触发事件,于是查看了下源码,如下:
private void initProcessActivationListener() {this.kruntime.addEventListener(new DefaultAgendaEventListener() {public void matchCreated(MatchCreatedEvent event) {String ruleFlowGroup = ((RuleImpl)event.getMatch().getRule()).getRuleFlowGroup();String ruleName;String processId;if ("DROOLS_SYSTEM".equals(ruleFlowGroup)) {ruleName = event.getMatch().getRule().getName();processId = "RuleFlowStateNode-";if (ruleName.startsWith(processId)) {int index = ruleName.lastIndexOf(45);index = ruleName.lastIndexOf(45, index - 1);String eventType = ruleName.substring(0, index);ProcessRuntimeImpl.this.kruntime.queueWorkingMemoryAction(ProcessRuntimeImpl.this.new SignalManagerSignalAction(eventType, event));} else if (ruleName.startsWith("RuleFlowStateEventSubProcess-") || ruleName.startsWith("RuleFlowStateEvent-") || ruleName.startsWith("RuleFlow-Milestone-") || ruleName.startsWith("RuleFlow-AdHocComplete-") || ruleName.startsWith("RuleFlow-AdHocActivate-")) {ProcessRuntimeImpl.this.kruntime.queueWorkingMemoryAction(ProcessRuntimeImpl.this.new SignalManagerSignalAction(ruleName, event));}} else {ruleName = event.getMatch().getRule().getName();if (ruleName.startsWith("RuleFlow-Start-")) {processId = ruleName.replace("RuleFlow-Start-", "");ProcessRuntimeImpl.this.startProcessWithParamsAndTrigger(processId, (Map)null, "conditional", true);}}}});this.kruntime.addEventListener(new DefaultAgendaEventListener() {public void afterRuleFlowGroupDeactivated(RuleFlowGroupDeactivatedEvent event) {if (ProcessRuntimeImpl.this.kruntime instanceof StatefulKnowledgeSession) {ProcessRuntimeImpl.this.signalManager.signalEvent("RuleFlowGroup_" + event.getRuleFlowGroup().getName() + "_" + ((StatefulKnowledgeSession)ProcessRuntimeImpl.this.kruntime).getIdentifier(), (Object)null);} else {ProcessRuntimeImpl.this.signalManager.signalEvent("RuleFlowGroup_" + event.getRuleFlowGroup().getName(), (Object)null);}}});}
这个监听器只有在使用jbpm工作流时才会触发
自定义元数据
在上边介绍的监听器中,我们可以拿到被触碰的规则的元数据,例如 ruleName、salience、enabled、ruleFlowGroup等,这些都是内置的属性,那么当我们想自定义一些业务属性,譬如:ruleCode , 在触碰这些规则的时候拿到该这么办呢?


规则继承
package itors.rules;
import com.example.demo.beans.TestInputrule "demo1"@ruleCode(code_1)dialect "mvel"whentestInput: TestInput(a == "1", b == 2)thenSystem.out.println("触发a1规则");endrule "demo2" extends "demo1"dialect "mvel"whentestInput: TestInput(c == 3)thenSystem.out.println("触发a1规则");end
这样的好处就是,当demo1条件更改后,demo2规则也会同时生效,会大大降低维护难度。
规则多分支
rule "demo3"dialect "mvel"whentestInput: TestInput(c == 3)do[test_input_then]testOuput: TestOutput(f == 4)thenSystem.out.println("触发a1规则");then[test_input_then]System.out.println("触发a1规则,part: test_input_then");end
其实完全可以写两个规则,因为那样会更清晰。
池化session
// KieSession kieSession = kieContainer.newKieSession();// 在这里采用池化方法获取kiesessionKieContainerSessionsPool kieContainerSessionsPool = kieContainer.newKieSessionsPool(10);KieSession kieSession = kieContainerSessionsPool.newKieSession();TestInput featureData = new TestInput();featureData.setA("1");featureData.setB(2);featureData.setC(3);TestOutput featureOutData = new TestOutput();//插入kieSession.addEventListener(new ExecutorAgendaEventListener());kieSession.addEventListener(new ExecutorRuleRuntimeEventListener());kieSession.addEventListener(new ExecutorProcessEventListener());kieSession.insert(featureData);kieSession.insert(featureOutData);//执行规则((InternalAgenda) kieSession.getAgenda()).activateRuleFlowGroup("a2");((InternalAgenda) kieSession.getAgenda()).activateRuleFlowGroup("a1");kieSession.fireAllRules();kieSession.dispose();
当然,如果你这么干,需要把kieContainerSessionsPool在项目启动后或初次加载时初始化好pool
本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!
