在 Drools 中设置和获取全局变量

时间:2021-02-19 00:08:11

标签: drools kie

我在drl文件中有这样的东西:

import java.lang.String

global String result;

rule ''Rule 1'' when some condition
    then 
result = "PASS";
kcontext.getKnowledgeRuntime().setGlobal("Result", result); // I got an "Unexpected global" exception.
System.out.println("result = "+ Result);

另外,我不知道如何从 MyService.java 类访问这个全局变量。

2 个答案:

答案 0 :(得分:0)

您的规则不应触及“kcontext”。你到底想做什么? result = "PASS" 足以设置全局值。

global String result

rule "Rule 1" 
when 
  // some condition
then 
  result = "PASS";
end

当然它不会像您希望的那样工作,因为您需要更改现有对象的值;你不能像那样覆盖它。某些选项可能是“ResultsHolder”类,您可以设置一个布尔变量;或者甚至是您可以调用设置的 AtomicBoolean

要使用全局触发规则,您需要在调用规则之前将全局对象添加到 KieBase:

var value = ...; // some OBJECT which you are going to pass in as a global

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

触发规则后,您将获得可以使用的对 value 的引用。这也是您不能将字符串作为全局变量传递并期望它们捕获更改的原因——Java 是按值传递,而不是按引用传递。


这是一个将结果传递出规则的示例。这个玩具应用会检查学生的考试成绩,然后决定他们是通过还是失败。

课程:

class Student {
  private String name;
  public String getName() { return this.name; }
  public void setName(String name) { this.name = name; }
}

class Exam {
  private String name;
  private Double score;
  public String getName() { return this.name; }
  public void setName(String name) { this.name = name; }
  public Double getScore() { return this.score; }
  public void setScore(String score) { this.score = score; }
}

class ExamResults {
  private List<String> results = new ArrayList<>();
  public void logResults( String name, Double score, boolean passed ) {
    this.results.add(name + " scored " + score + "%, which is a " + (passed ? "passing": "failing") + " grade.");
  }
  public List<String> getResults() { return this.results; }
}

规则:

global ExamResults results;

rule "Evaluate exam"
when
  Student( $name: name )
  Exam ( $score: score, name == $name )
then
  boolean passed = $score > 60.0;
  results.logResults( $name, $score, passed );
end

调用:

List<Student> students = ...;
List<Exam> exams = ... ;
ExamResults results = new ExamResults();

KieSession session = ruleBase.newStatefulSession();
students.forEach( student -> session.insert(students) );
exams.forEach( exam -> session.insert(exam) );
session.setGlobal( "results", results);
session.fireAllRules();

// Print the results:
results.getResults().forEach(System.out::println);

如果您只是想从规则中获取一些数据(例如某些条件是否匹配),我之前已经写过关于如何做到这一点的答案here 和 {{3} }.如果您只想知道触发了哪些规则,您应该编写一个 here 来记录规则命中(“afterMatchFired”)。

答案 1 :(得分:0)

我试图从 drl 文件中设置一个全局变量,而不是像 Service 类那样的 java 类。

我所要做的就是以下操作并且成功

导入 java.lang.String

全局字符串结果;

规则''规则1'' 当
一些条件

然后

String grade = "PASS";

kcontext.getKnowledgeRuntime().setGlobal("result", grade);  
                                                                                                                

结束

此外,全局变量名称应该与我在 setGlobal("result",...) 上传递的名称相匹配。

然后使用我在 Service 类中的会话获取全局变量。喜欢:

session.getGlobal("result");