【问题标题】:Drools- how to find out which all rules were matched?Drools-如何找出所有匹配的规则?
【发布时间】:2013-11-25 22:36:36
【问题描述】:

我有一个 .DRL 文件,其中包含 10 条规则。一旦我插入一个事实,一些规则可能会被匹配——我如何找出哪些规则以编程方式匹配?

【问题讨论】:

    标签: java drools rule-engine


    【解决方案1】:

    您可以使用 RuleContext:drools 打印有关从 DRL 文件本身执行的规则的信息

    System.out.println(drools.getRule().getName())
    

    【讨论】:

      【解决方案2】:

      请注意,此答案适用于 Drools 最高 5.x 的版本。如果您已升级到 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<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();
              }
          }
      
      }
      

      【讨论】:

      • 请用@melchoir55 的答案更新您的答案,因为它不再适用于实际版本
      【解决方案3】:

      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();
              }
          }
      
      }
      

      【讨论】:

      • 它会抛出异常:java.util.ConcurrentModificationException: null at java.util.HashMap$HashIterator.nextEntry(HashMap.java:922) ~[na:1.7.0_60] at java.util。 HashMap$KeyIterator.next(HashMap.java:956) ~[na:1.7.0_60] at org.drools.core.impl.StatelessKnowledgeSessionImpl.registerCustomListeners(StatelessKnowledgeSessionImpl.java:188) ~[drools-core-6.2.0.Final .jar:6.2.0.Final] 在 org.drools.core.impl.StatelessKnowledgeSessionImpl.newWorkingMemory(StatelessKnowledgeSessionImpl.java:140)
      【解决方案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
      

      【讨论】:

        【解决方案5】:

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

        从 java 文件中插入一个 HashMap 到 DRL 文件(使用 Drools 会话概念), 它应该包含规则名称作为键和布尔值作为结果。

        关注link 了解如何将地图插入 DRL 文件。

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

        希望这会有所帮助:)

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2018-10-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2022-01-14
          • 1970-01-01
          相关资源
          最近更新 更多