如何在 Drools 文件中传递多个对象并提取所需的对象

如何解决如何在 Drools 文件中传递多个对象并提取所需的对象

我真的是 Drools 的新手。对于一个项目,我试图将多个对象传递到 drl 文件中,但我不知道如何在同一规则中处理多个对象!

这是我的流口水逻辑:

rule "SNAP when Employed"
    
    when
        citizenDataObject: CitizenData(planName=="SNAP" && employed==true)
    then
        PlanData planDataObject= new PlanData();
        planDataObject.setPlanStatus("DN");
        planDataObject.setDenialReason("Salaried Employee");
    end

当我执行此规则时,我无法检索 planDataObject。

在java端,我传递CitizenData对象和PlanData对象:

WorkingMemory workingMemory = ruleBase.newStatefulSession();
workingMemory.insert(citizenData);
workingMemory.insert(planData);
workingMemory.fireAllRules();

解决方法

有多种方法可以从规则中获取数据。它们是:

  1. 调用具有副作用的操作。
  2. 设置/修改全局变量。
  3. 使用事实句柄从工作内存中提取数据。

第一个是最简单的,也是我建议做的。第二个是我们在“旧时代”(大约 10 年前,使用 Drools 5)过去的做法。最后一个在技术上可能但非常复杂,我从未做过。

我已在对 this other question 的回答中涵盖了所有这些内容,我认为它是重复的,但由于没有赞成的答案,因此无法投票。


有副作用的动作

这是推荐的方法。具有副作用的操作是您调用的可以在规则之外看到的操作。一个极端的例子可能是保存到数据库,但一个更简单的例子可能是将一个对象添加到列表中。

以这个玩具情况为例。如果学生有超过 3 次无故缺勤,则会生成一张便条并将其寄回家给父母。以下是我们可以对这种情况进行建模的两种方式。一个规则是将注释添加到学生对象本身的变量中。另一个规则调用一个效用函数将笔记发送给父母。第三个将规则添加到笔记集。

rule "Unexcused absences: notify by adding note to the student record"
when
  $student: Student( absences >= 3,$name: name )
then
  $student.addNote( "Student '" + $name + "' has had too many unexcused absences");
end

rule "Unexcused absences: notify by email"
when
  $student: Student( absences >= 3,$name: name )
  $emailSystem: MailSystem() // Some utility class which can send emails
then
  $emailSystem.sendNote(
    $student,"Student '" + $name + "' has had too many unexcused absences"
  );
end

rule "Unexcused absences: append note to a list"
when
  Student( absences >= 3,$name: name )
  $notes: List()
then
  $notes.add("Student '" + $name + "' has had too many unexcused absences.");
end

所有这些规则的工作方式是它们更改外部应用程序(邮件系统)或输入对象(学生或笔记列表)中的数据。规则生效后,这些副作用将被外界看到。


全局变量

这是旧的做事方式,全局变量。它们通常与 Java 中的静态变量相同,但您不能依赖它们来跟踪规则执行之间的数据。 (就像静态变量和线程一样,规则可见的数据有点复杂。)

但如果我们只想跟踪规则输出,这是一个可行的替代方案。

首先,在调用如下规则之前,您针对会话设置了一个全局变量:

KieSession session = ruleBase.newStatefulSession();
session.insert(...); // insert data
session.setGlobal( "myGlobalFoo",value ); // sets the global; note the name must match the rule file!
session.fireAllRules();

然后在您的规则文件中,您将使用 global 关键字在文件顶部、导入下方声明您的全局变量。您的全局名称必须与您传递给 setGlobal 方法的名称完全匹配。

使用与之前相同的示例(缺勤 3 次以上的学生收到一封寄回家的便条),我们可以使用如下全局变量。在第一个示例中,我们可以使用 List<string> notes 发送回家的笔记,并将其设置为全局:

global List notes;

rule "Student absences: add note to global List"
when
  Student( absences >= 3,$name: name )
then
  notes.add("Student '" + $name + "' has been absent too many times!");
end

一旦所有规则都被触发,你传递给全局的对象就会添加值。请注意,保留对对象的引用很重要——不要调用 session.setGlobal("notes",new ArrayList<>()) 之类的东西!那样你就不会参考那个笔记列表。

KieSession javadoc 谈到了一些全局变量以及一些注意事项。


第三种方法是使用事实句柄提取数据。这没有得到很好的记录,我也没有亲自做过,但应该是可能的。通常它用于保持对传递到工作内存的数据的“句柄”,以便您可以将其取出用于单元测试或诸如此类。我认为有可能定位并提取您新实例化的数据。

我个人不会走这条路,因为它不是标准的工作流程,而且与 Drools 库的其他部分相比,围绕这些 API 的文档很差(因为这主要用于内部和测试。)

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其他元素将获得点击?
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。)
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbcDriver发生异常。为什么?
这是用Java进行XML解析的最佳库。
Java的PriorityQueue的内置迭代器不会以任何特定顺序遍历数据结构。为什么?
如何在Java中聆听按键时移动图像。
Java“Program to an interface”。这是什么意思?
Java在半透明框架/面板/组件上重新绘画。
Java“ Class.forName()”和“ Class.forName()。newInstance()”之间有什么区别?
在此环境中不提供编译器。也许是在JRE而不是JDK上运行?
Java用相同的方法在一个类中实现两个接口。哪种接口方法被覆盖?
Java 什么是Runtime.getRuntime()。totalMemory()和freeMemory()?
java.library.path中的java.lang.UnsatisfiedLinkError否*****。dll
JavaFX“位置是必需的。” 即使在同一包装中
Java 导入两个具有相同名称的类。怎么处理?
Java 是否应该在HttpServletResponse.getOutputStream()/。getWriter()上调用.close()?
Java RegEx元字符(。)和普通点?