我有一个 .DRL 文件,其中包含 10 条规则。一旦我插入一个事实,一些规则可能会被匹配——我如何找出哪些规则以编程方式匹配?
问问题
36860 次
5 回答
25
请注意,此答案适用于 Drools 最高 5.x 的版本。如果您已升级到 6 或更高版本,请查看来自 @melchoir55 的修改后的答案。我自己没有测试过,但我相信它可以工作。
要跟踪规则激活,您可以使用 AgendaEventListener。下面是一个示例,如下所示:
您只需要创建这样的侦听器并将其附加到会话,如下所示:
ksession = kbase.newStatefulKnowledgeSession();
AgendaEventListener agendaEventListener = new TrackingAgendaEventListener();
ksession.addEventListener(agendaEventListener);
//...
ksession.fireAllRules();
//...
List<Activation> activations = agendaEventListener.getActivationList();
请注意,还有 WorkingMemoryEventListener,它使您能够跟踪事实的插入、更新和撤回。
跟踪和记录 AgendaEventListener 的代码:
package com.sctrcd.drools.util;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import org.drools.definition.rule.Rule;
import org.drools.event.rule.DefaultAgendaEventListener;
import org.drools.event.rule.AfterActivationFiredEvent;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* A listener that will track all rule firings in a session.
*
* @author Stephen Masters
*/
public class TrackingAgendaEventListener extends DefaultAgendaEventListener {
private static Logger log = LoggerFactory.getLogger(TrackingAgendaEventListener.class);
private List<Activation> activationList = new ArrayList<Activation>();
@Override
public void afterActivationFired(AfterActivationFiredEvent event) {
Rule rule = event.getActivation().getRule();
String ruleName = rule.getName();
Map<String, Object> ruleMetaDataMap = rule.getMetaData();
activationList.add(new Activation(ruleName));
StringBuilder sb = new StringBuilder("Rule fired: " + ruleName);
if (ruleMetaDataMap.size() > 0) {
sb.append("\n With [" + ruleMetaDataMap.size() + "] meta-data:");
for (String key : ruleMetaDataMap.keySet()) {
sb.append("\n key=" + key + ", value="
+ ruleMetaDataMap.get(key));
}
}
log.debug(sb.toString());
}
public boolean isRuleFired(String ruleName) {
for (Activation a : activationList) {
if (a.getRuleName().equals(ruleName)) {
return true;
}
}
return false;
}
public void reset() {
activationList.clear();
}
public final List<Activation> getActivationList() {
return activationList;
}
public String activationsToString() {
if (activationList.size() == 0) {
return "No activations occurred.";
} else {
StringBuilder sb = new StringBuilder("Activations: ");
for (Activation activation : activationList) {
sb.append("\n rule: ").append(activation.getRuleName());
}
return sb.toString();
}
}
}
于 2013-11-13T14:18:14.347 回答
22
Steve 的回答是可靠的,但是 drools 6 带来的主要变化使代码过时了。我在下面发布了考虑到新 api 的史蒂夫代码的重写:
package your.preferred.package;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import org.drools.core.event.DefaultAgendaEventListener;
import org.kie.api.definition.rule.Rule;
import org.kie.api.event.rule.AfterMatchFiredEvent;
import org.kie.api.runtime.rule.Match;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* A listener that will track all rule firings in a session.
*
* @author Stephen Masters, Isaac Martin
*/
public class TrackingAgendaEventListener extends DefaultAgendaEventListener {
private static Logger log = LoggerFactory.getLogger(TrackingAgendaEventListener.class);
private List<Match> matchList = new ArrayList<Match>();
@Override
public void afterMatchFired(AfterMatchFiredEvent event) {
Rule rule = event.getMatch().getRule();
String ruleName = rule.getName();
Map<String, Object> ruleMetaDataMap = rule.getMetaData();
matchList.add(event.getMatch());
StringBuilder sb = new StringBuilder("Rule fired: " + ruleName);
if (ruleMetaDataMap.size() > 0) {
sb.append("\n With [" + ruleMetaDataMap.size() + "] meta-data:");
for (String key : ruleMetaDataMap.keySet()) {
sb.append("\n key=" + key + ", value="
+ ruleMetaDataMap.get(key));
}
}
log.debug(sb.toString());
}
public boolean isRuleFired(String ruleName) {
for (Match a : matchList) {
if (a.getRule().getName().equals(ruleName)) {
return true;
}
}
return false;
}
public void reset() {
matchList.clear();
}
public final List<Match> getMatchList() {
return matchList;
}
public String matchsToString() {
if (matchList.size() == 0) {
return "No matchs occurred.";
} else {
StringBuilder sb = new StringBuilder("Matchs: ");
for (Match match : matchList) {
sb.append("\n rule: ").append(match.getRule().getName());
}
return sb.toString();
}
}
}
于 2015-12-31T01:00:00.840 回答
4
您可以使用静态记录器工厂,它将使用您喜欢的记录器记录 DRL 文件中的操作。
例如:
import org.drools.runtime.rule.RuleContext;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public final class DRLLogger {
private DRLLogger() {
}
protected static Logger getLogger(final RuleContext drools) {
final String category = drools.getRule().getPackageName() + "." + drools.getRule().getName();
final Logger logger = LoggerFactory.getLogger(category);
return logger;
}
public static void info(final RuleContext drools, final String message, final Object... parameters) {
final Logger logger = getLogger(drools);
logger.info(message, parameters);
}
public static void debug(final RuleContext drools, final String message, final Object... parameters) {
final Logger logger = getLogger(drools);
logger.debug(message, parameters);
}
public static void error(final RuleContext drools, final String message, final Object... parameters) {
final Logger logger = getLogger(drools);
logger.error(message, parameters);
}
}
然后从您的 DRL 文件中:
import function com.mycompany.DRLLogger.*
rule "myrule"
when
$fact: Fact()
then
info(drools, "Fact:{}", $fact);
end
于 2013-11-14T09:24:10.517 回答
0
在 DRL 文件中将方言更改为 JAVA。
将 java 文件中的 HashMap 插入 DRL 文件(使用 Drools 会话概念),其中应包含规则名称作为键和布尔值作为结果。
按照此链接了解如何将 Map 插入 DRL 文件。
您现在可以找到完全匹配的规则。
希望这可以帮助 :)
于 2013-11-13T11:47:45.573 回答
0
您可以使用 RuleContext:drools 打印有关从 DRL 文件本身执行的规则的信息
System.out.println(drools.getRule().getName())
于 2019-03-15T08:04:08.280 回答