Drools入门之global全局变量

全局变量是一个很有用的元素节点,它是通过关键字global class(对象类型)name组成的。class可以是任意的,能为规则提供操作数据或服务等功能,特别是在规则RHS部分中使用程序提供的服务功能,如在RHS部分添加日志功能、修改数据表、发送E-mail等。

global全局变量与Fact(事实)对象不同,不会因为值变化而影响到规则的再次激活。

接下来,我们看一个例子。

public class RulesHello {
    public static void main(String[] args) {
        KieServices kieService = KieServices.Factory.get();
        KieContainer kieContainer = kieService.getKieClasspathContainer();
        KieSession kieSession = kieContainer.newKieSession("testGlobal");
        kieSession.setGlobal("count",2017);
        int count = kieSession.fireAllRules();
        System.out.println("kieSession getGlobal:" + kieSession.getGlobal("count"));
        System.out.println("总共执行了"+count+"条规则");
        kieSession.dispose();
    }
}
<kbase name="global" packages="rules.isGlobal">
        <ksession name="testGlobal"/>
</kbase>
package rules.isGlobal;
dialect  "mvel"

import com.domain.Person
global java.lang.Integer count

rule "global1"
    when
    then
    System.out.println("global1 修改之前---->"+count);
    count = 10;
    System.out.println("global1 修改之后---->"+count);
end

rule "global2"
    when
    then
    System.out.println("global2 直接输出---->"+count);
end

rule "global3"
    when
     $total : Double() from
       accumulate(Person(),
                  init(Double totls = 0.0),
                    action(
                    System.out.println("global3 LHS修改之前---->"+count);
                    count=20;
                    totls+=1;
                    System.out.println("global3 LHS修改之后---->"+count);
                    ),
                  reverse( totls-=1;),
                  result( totls )
         )
    then
    System.out.println("global3 RHS修改之前---->"+count);
    count = 90;
    System.out.println("global3 RHS修改之后---->" + count);
end

这个例子中,有三条规则,第一条规则在RHS中对全局变量进行修改,分别在修改前后,输出了全局变量的值。第二条规则没有修改全局变量,直接进行了输出,第三条规则的LHS中用到了内置函数,后面会介绍,主要是在LHS的修改前后输出了值,以及RHS修改前后输出了值。

我们来看一下日志

global1 修改之前---->2017
global1 修改之后---->10
global2 直接输出---->2017
global3 RHS修改之前---->2017
global3 RHS修改之后---->90
kieSession getGlobal:2017
总共执行了3条规则

通过控制台的输出结果可以看出,当前规则体中修改的值包装类的全局变量只会影响到当前规则体。

如果多个package使用相同标识声明的全局变量,那么它们的类型必须是相同的,并且它们所有引用都是相同的全局变量。

全局变量定义成常量或包装类型时,该值对整个规则而言是不变的。但并不提倡用于数据共享。原因是针对不同类型全局变量中的内容也可能会发生变化。全局变量如果定义成集合类或JavaBean时,在规则体RHS部分中进行修改,则规则库或Java代码中的值都会发生变化。这证明了全局变量并非不可变的值,但也正是这一点会引发出一个问题,如果在多个地方使用并修改了全局变量,就可能会导致最终结果并不是设计师所想的。

使用全局变量时应注意点以下几点。

(1)常量值是不能改变的。

(2)包装类是不能改变的。

(3)类似JavaBean、List类的操作是可以改变内容的,但内存地址不会变。


Drools入门之global全局变量
https://www.zhaojun.inkhttps://www.zhaojun.ink/archives/drools-global
作者
卑微幻想家
发布于
2022-06-29
许可协议