【问题标题】:how to correctly fire Drools rules on multiple objects?如何在多个对象上正确触发 Drools 规则?
【发布时间】:2019-10-08 22:22:28
【问题描述】:

我第一次接触 Drools(使用 java),我对它的会话和处理对象集合的能力感到很困惑。 就是这样:

我正在构建一个由 rest-services 组成的 Web 应用程序。

我有一个名为 Log 的类,它有两个字段( eventType 和 RiskLevelId )。

Mycode 在定义的时间范围内从数据库中检索多个此类对象。

如果此对象集合恰好包含一个事件类型 == 2 和风险级别 ID == 1 的日志,以及另一个事件类型 == 3 和风险级别 ID == 1 的日志,则应执行该规则。

通过 Drools 接口,我正确检索了 KieServices、KieBuilder、KieContaier、KieBase 和 KieSession。

try {
        // load up the knowledge base
        KieServices kieServices = KieServices.Factory.get();
        KieFileSystem kfs = kieServices.newKieFileSystem();
        FileInputStream fis = f;
        kfs.write( "src/main/resources/simple.drl",
                kieServices.getResources().newInputStreamResource( fis ) );
        KieBuilder kieBuilder = kieServices.newKieBuilder( kfs ).buildAll();
        Results results = kieBuilder.getResults();
        if( results.hasMessages( Message.Level.ERROR ) ){
            System.out.println( results.getMessages() );
            throw new IllegalStateException( "### errors ###" );
        }
        KieContainer kieContainer = kieServices.newKieContainer( kieServices.getRepository().getDefaultReleaseId() );
        KieBase kieBase = kieContainer.getKieBase();
        kieSession = kieContainer.newKieSession();




    }catch (Throwable t) {
        t.printStackTrace();
    }

然后我在 for 循环中检索每个单独的 Log 实例。留在循环中,我还将对象添加到 KieSession 并触发规则:

@Autowired
KieSessionFactory kieSessionFactory;



@Override
public void run() {

    KieSession kieS =  kieSessionFactory.getKieSessionCheckSavedLog();

    try {
        List<Log> logs = logRepo.getAllInGivenTimeSec(10);
        for(Log l : logs) {
            kieS.insert(l);
            kieS.fireAllRules();
        }
    } catch (Exception e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }

}

这是我写的规则:

package com.sample 
import it.protodrools.beans.Log;

dialect "java"

rule "log2"
    when
        $l1 : Log( eventType == 2 && riskLevelId == 1);
        $l2 : Log( this != $l1 && eventType == 3 && riskLevelId == 1 );
    then
       System.out.println( "deadly threat !" );
end

我的问题是:这条规则是否会考虑到我传递的整个对象列表(虽然不是通过列表,因为我已经读过这不是一个好习惯),因此考虑是否存在条件匹配我通过的对象中的一对对象?

woukd 你建议一些不同的解决方法?

提前致谢

【问题讨论】:

    标签: java drools


    【解决方案1】:

    不,不会的。

    for(Log l : logs) {
        kieS.insert(l);
        kieS.fireAllRules();
    }
    

    根据您的循环,您将插入一个对象,并在每次插入后立即触发所有规则。我不确定 Drools 会如何对您的循环做出反应,但您可能想要做的是将所有日志插入工作内存中,然后触发规则:

    for(Log l : logs) {
        kieS.insert(l);
    }
    kieS.fireAllRules();
    

    设计一个 JUnit 测试类会立即向您展示这一点。

    【讨论】:

    • +1 表示 TDD。可能还值得考虑自动作用于集合的无状态会话。
    猜你喜欢
    • 2015-02-03
    • 1970-01-01
    • 1970-01-01
    • 2016-06-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-30
    相关资源
    最近更新 更多