简体   繁体   English

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

[英]Setting and getting a Global variable in Drools

I have something like this in drl file:我在 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);

Also, I don't know how to access this global variable from my MyService.java class.另外,我不知道如何从 MyService.java class 访问这个全局变量。

Your rule should not be touching the 'kcontext'.您的规则不应触及“kcontext”。 What in the world are you trying to do?你到底想做什么? result = "PASS" is sufficient for setting the value of the global. result = "PASS"足以设置全局的值。

global String result

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

Of course it's not going to work like you want it to because you need to change the value of the existing object;当然,它不会像您希望的那样工作,因为您需要更改现有 object 的值; you can't overwrite it like that.你不能那样覆盖它。 Some options might be a "ResultsHolder" sort of class with a boolean variable you can set;某些选项可能是 class 的“ResultsHolder”类型,您可以设置 boolean 变量; or maybe even an AtomicBoolean that you can call set on.或者甚至是你可以调用的AtomicBoolean

To fire rules with a global, you need to add the global objects to the KieBase before invoking your rules:要使用全局触发规则,您需要在调用规则之前将全局对象添加到 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();

After the rules are fired, you'll have your reference to value that you can use.触发规则后,您将获得对可以使用的value的引用。 This is also why you can't pass strings as globals and expect them to capture changes -- Java is pass-by-value, not pass-by-reference.这也是为什么您不能将字符串作为全局变量传递并期望它们捕获更改的原因——Java 是按值传递,而不是按引用传递。


Here's an example for passing results out of the rules.这是将结果传递到规则之外的示例。 This toy app will check the student's score on a test and then decide if they passed or failed.这个玩具应用程序将检查学生的考试成绩,然后决定他们是通过还是失败。

Classes:课程:

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

Rule:规则:

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

Invocation:调用:

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

If all you're trying to do is to get some data out of your rules (eg whether certain conditions match), I've written up answers about how to do that previously here and here .如果您要做的只是从您的规则中获取一些数据(例如,某些条件是否匹配),我已经在此处此处编写了有关如何执行此操作的答案。 If you just want to know what rules triggered, you should write a listener which logs rule hits ("afterMatchFired").如果您只想知道触发了哪些规则,您应该编写一个记录规则命中的侦听器(“afterMatchFired”)。

I was trying to set a global variable from the drl file not my java class like Service class.我试图从drl文件中设置一个全局变量,而不是我的java class,如服务class。

All I had to do was the following and it worked successfully我所要做的就是以下,它成功地工作了

import java.lang.String导入 java.lang.String

global String result;全局字符串结果;

rule ''Rule 1'' when规则“规则 1”时
some condition一些条件

then然后

String grade = "PASS";

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

end结尾

Also, the global variable name should match what I pass on the setGlobal("result",...).此外,全局变量名称应与我在 setGlobal("result",...) 上传递的名称相匹配。

And then get the global variable using the session I have in the Service class.然后使用我在服务 class 中的 session 获取全局变量。 like:喜欢:

session.getGlobal("result"); session.getGlobal("结果");

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM