文章目录
监听器
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.TestInput
rule "demo1"
@ruleCode(code_1)
dialect "mvel"
when
testInput: TestInput(a == "1", b == 2)
then
System.out.println("触发a1规则");
end
rule "demo2" extends "demo1"
dialect "mvel"
when
testInput: TestInput(c == 3)
then
System.out.println("触发a1规则");
end
这样的好处就是,当demo1条件更改后,demo2规则也会同时生效,会大大降低维护难度。
规则多分支
rule "demo3"
dialect "mvel"
when
testInput: TestInput(c == 3)
do[test_input_then]
testOuput: TestOutput(f == 4)
then
System.out.println("触发a1规则");
then[test_input_then]
System.out.println("触发a1规则,part: test_input_then");
end
其实完全可以写两个规则,因为那样会更清晰。
池化session
// KieSession kieSession = kieContainer.newKieSession();
// 在这里采用池化方法获取kiesession
KieContainerSessionsPool 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