Drools-如何找出所有规则匹配?

我有一个.DRL文件,它说了10个规则。 一旦我插入事实,可能会匹配一些规则 – 如何找出以编程方式匹配的规则?

请注意,此答案适用于最高达5.x的Drools版本。 如果您已经升级到6或以上,请查看@ melchoir55的修改后的答案。 我自己没有测试过,但我相信它有效。

要跟踪规则激活,可以使用AgendaEventListener。 以下是一个示例,如下所示:

https://github.com/gratiartis/sctrcd-payment-validation-web/blob/master/src/main/java/com/sctrcd/drools/util/TrackingAgendaEventListener.java

您只需要创建这样一个侦听器并将其附加到会话中,如下所示:

ksession = kbase.newStatefulKnowledgeSession(); AgendaEventListener agendaEventListener = new TrackingAgendaEventListener(); ksession.addEventListener(agendaEventListener); //... ksession.fireAllRules(); //... List 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 activationList = new ArrayList(); @Override public void afterActivationFired(AfterActivationFiredEvent event) { Rule rule = event.getActivation().getRule(); String ruleName = rule.getName(); Map 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 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(); } } } 

史蒂夫的答案是可靠的,但流口水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 matchList = new ArrayList(); @Override public void afterMatchFired(AfterMatchFiredEvent event) { Rule rule = event.getMatch().getRule(); String ruleName = rule.getName(); Map 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 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(); } } } 

您可以使用静态记录器工厂,该工厂将使用您喜欢的记录器记录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 

在DRL文件中将方言更改为JAVA。

将Java文件中的HashMap插入DRL文件(使用Drools会话概念),该文件应包含规则名称作为键,布尔值作为结果。

请点击此链接以了解如何将地图插入DRL文件。

您现在可以找到完全匹配的规则。

希望这可以帮助 :)