drools规则引擎kie最佳实践

监听器

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

  • 3
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 7
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值