我正在尝试使用Drools编写一个基于规则的引擎。规则如下:
规则“警报”:如果状态为“警报”,请立即发送通知。
规则“警告”:如果状态为“警告”,则将设备ID保存在内存中并等待5分钟。如果在5分钟内收到另一条具有相同设备ID和状态“已解决”的消息,则取消此规则。否则,将状态升级为Alarm并触发规则“Alarm”。
规则“已解决”:如果状态为“已解决”并且设备ID已在内存中,则清除该设备ID的“警告”,即从内存中删除设备ID。
规则警报很容易并且正在工作。但是规则警告和已解决显然在我的代码中不起作用。如何在Drools中编写这样的规则?
以下是我迄今为止编写的代码:
package com.sample;
import org.drools.KnowledgeBase;
import org.drools.KnowledgeBaseFactory;
import org.drools.builder.KnowledgeBuilder;
import org.drools.builder.KnowledgeBuilderError;
import org.drools.builder.KnowledgeBuilderErrors;
import org.drools.builder.KnowledgeBuilderFactory;
import org.drools.builder.ResourceType;
import org.drools.io.ResourceFactory;
import org.drools.logger.KnowledgeRuntimeLogger;
import org.drools.logger.KnowledgeRuntimeLoggerFactory;
import org.drools.runtime.StatefulKnowledgeSession;
public class DroolsTest {
public static final void main(String[] args) {
try {
// load up the knowledge base
KnowledgeBase kbase = readKnowledgeBase();
StatefulKnowledgeSession ksession = kbase.newStatefulKnowledgeSession();
KnowledgeRuntimeLogger logger = KnowledgeRuntimeLoggerFactory.newFileLogger(ksession, "test");
// go !
MachineMessage[] messages = new MachineMessage[4];
messages[0] = new MachineMessage("1", "Warning");
messages[1] = new MachineMessage("2", "Alarm");
messages[2] = new MachineMessage("3", "Alarm");
messages[3] = new MachineMessage("1", "Resolved");
for(int i = 0; i < messages.length; i++)
{
ksession.insert(messages[i]);
ksession.fireAllRules();
Thread.sleep(9000);
}
logger.close();
} catch (Throwable t) {
t.printStackTrace();
}
}
private static KnowledgeBase readKnowledgeBase() throws Exception {
KnowledgeBuilder kbuilder = KnowledgeBuilderFactory.newKnowledgeBuilder();
kbuilder.add(ResourceFactory.newClassPathResource("Sample.drl"), ResourceType.DRL);
KnowledgeBuilderErrors errors = kbuilder.getErrors();
if (errors.size() > 0) {
for (KnowledgeBuilderError error: errors) {
System.err.println(error);
}
throw new IllegalArgumentException("Could not parse knowledge.");
}
KnowledgeBase kbase = KnowledgeBaseFactory.newKnowledgeBase();
kbase.addKnowledgePackages(kbuilder.getKnowledgePackages());
return kbase;
}
public static class MachineMessage {
private String deviceID;
private String status;
public MachineMessage() { }
public MachineMessage(String deviceID, String status) {
this.deviceID = deviceID;
this.status = status;
}
public String getDeviceID() {
return this.deviceID;
}
public void setDeviceID(String deviceID) {
this.deviceID = deviceID;
}
public String getStatus() {
return this.status;
}
public void setStatus(String status) {
this.status = status;
}
}
}
package com.sample
import com.sample.DroolsTest.MachineMessage;
rule "Alarm"
when
m : MachineMessage( status == "Alarm", myDeviceID : deviceID )
then
System.out.println("Send notification to technician, device in Alarm state. Device ID: " + myDeviceID );
end
rule "Warning"
when
m : MachineMessage( status == "Warning", myDeviceID : deviceID )
then
System.out.println("Wait for 5 minutes, device in Warning state. Device ID: " + myDeviceID);
// if we get Machine Message with the same device ID and Resolved status in 5 minutes then
// we'll not trigger the following line
m.setStatus("Alarm");
update(m);
end
rule "Resolved"
when
m : MachineMessage( status == "Resolved", myDeviceID : deviceID )
then
System.out.println("Device has resolved its warning state. Device ID: " + myDeviceID);
end
我得到的实际输出是:
Wait for 5 minutes, device in Warning state. Device ID: 1
Send notification to technician, device in Alarm state. Device ID: 1
Send notification to technician, device in Alarm state. Device ID: 2
Send notification to technician, device in Alarm state. Device ID: 3
Device has resolved its warning state. Device ID: 1
鉴于我想要:
Wait for 5 minutes, device in Warning state. Device ID: 1
Send notification to technician, device in Alarm state. Device ID: 2
Send notification to technician, device in Alarm state. Device ID: 3
Device has resolved its warning state. Device ID: 1
根据Drools文档,CEP事件应该是不可变的:
作为最佳实践,允许应用程序填充未填充的事件属性(以使用推断数据丰富事件),但绝不应更改已填充的属性。
因此,从OP提出的方式来看,“警告”规则显然已经无法满足CEP的第一个要求(改变字段“状态”)。
可能的建议如下:
rule "Warning"
when
m : MachineMessage( status == "Warning", myDeviceID : deviceID )
not( MachineMessage( status == "Resolved", deviceID == m.deviceID, this after[0s, 30s] m) )
then
System.out.println("I waited for 5 minutes, device in Warning state not followed by Resolved. Device ID: " + myDeviceID);
insert(new MachineMessage(m.deviceID, "Alarm"));
end
这不会改变现有事件的任何有价字段,并且实际上会使CEP知识推理试图匹配OP描述的业务需求。
一般来说,Drools手册中的喷水器/火灾报警器CEP示例似乎与OP描述的业务要求一致。
Thx回答。
我们正在使用JBoss Drools来外部化我们正在构建的某些服务中一些特别容易更改的业务逻辑。 在我们的开发人员可以创建和维护这些规则的地方,这些规则运行得很好,我们有很好的集成水平和集成工作流。 我们希望将其应用扩展到一种需要非常高级别定制的新服务。本质上,“专家用户”需要能够设置两种不同类型的规则: > “标准”规则-这些几乎是隐含的规则,我们知道这些规则是常见的需求,我们可以构建UI来设置
我的项目使用drools专家手段(DRL)文件。在规则文件中,如果用户想删除和更新规则,应该怎么做? 规则文件: 例如,用户希望将温度值更改为30.0。
我有一套规则,每15秒触发一次。 由于我想对这些规则进行单元测试,所以我想动态设置这个持续时间值。此外,我想把它放在我的应用程序的配置中。此值可能用于20多条规则。 我该怎么做?有可能吗? 这是我的规则: 我想要的是: 我尝试:-从单元测试中放入一个长全局变量集-从单元测试中放入一个包含“15s”的字符串全局变量集-导入一个包含静态字段的类,然后 看来没有办法了A I right?有什么建议吗?
我对口水还不熟悉。我试图理解Drools提供的无状态会话和有状态会话之间的区别。 根据我的初步理解, 在无状态会话的情况下,如果在任何规则的操作执行过程中修改了事实,则不会将其重新提交给推理引擎以找出与修改后的事实匹配的新规则。 在状态会话的情况下,如果在任何规则的操作执行过程中修改了事实,则它将被重新提交给推理引擎以找出与修改后的事实相匹配的新规则,然后执行相应的操作。 因此,当我试图通过编写一
08:00:59得分10*5=>50 08:01:00得分9*5=>45 似乎在08:00:59计算分数,在08H01:00进行分数验证 此外,我看到移动是从当前代理到当前代理。这样可以吗?