此语法是用来定义全局变量的,被用于提供应用程序对象的规则,一般来说,global是用于提供数据或者服务使用的规则,特别是应用程序服务中使用规则的后果,并返回数据规则, 全局变量不插入到工作记忆,因此全球不应该用于建立条件规则除非它有一个恒定不变的价值。引擎不能通知全局变量的值改变时,不跟踪他们的变化。不正确的使用全局约束可能产生意外的结果虽然不会改变global变量的值或者内容,但是如果在同一个段代码中改变了global值,在这段code中,就用使用被修改后的global值,但其他code中的value是不会变的,我们可以理解成为global的一个副本。用法其实很简单:
Drl文件:
global java.util.List myGlobalList; rule "Using a global" when eval( true ) then myGlobalList.add( "Hello World" ); end
List list = new ArrayList(); KieSession kieSession = kiebase.newKieSession(); kieSession.setGlobal( "myGlobalList", list );
类型是一致,变量名也要一致,因为setGlobal是一个map(看源码就知道了)。
注意, 它们只是命名对象的实例, 从你的应用程序传入到工作内存的。 这意味着你可以传递任何对象:你可以传入一个服务的定位器,或者服务自身。利用新的 from 元素,现在通常是传入一个 Hibernate会话作为全局变量,允许 from 从命名的 Hibernate 查询拉数据。
一个例子可以是一个 Email 服务实例。在你调用规则引擎的集成代码中,你获取你的 emailService 对象,然后在工作内存中设置它。在 DRL 中,你声明你有一个 EmailService 类型的全局对象,并且给它命名为 "email"。然后在你的规则推论中,你可以使用如 email.sendSMS(number, message)这样的东西。
全局变量不是设计来在规则之间共享数据的,决不能用于这样的目的。规则总是推断和作用于工作内在的状态,所以,如果你想从规则到规则传递数据,断言数据作为事实到工作内存中。
我们强烈反对从你的规则内部设置或改变全局变量的值。 我们建议你总是从你的应用程序中使用工作内存的接口设置该值
在使用全局变量Global时要注意,当我们传入的值是包装类型(注:不能传基本类型)或者是
javabean或者是集合时,我们是可以使用这些类型的内部属性及方法的。
举个简单的例子说明一下:
global com.jars1.jars1.Person perosn; perosn.getName(); Person p=new Person(); p.setName("global"); ksession.setGlobal("perosn",p);
从上面的例子中,可以看出来,Person中的属性及方法是可以用的,包装类、集合及接口实现亦如此。这样一来,我们就可能在全局变量中进行一些java的操作了,比如操作数据库,webService,redis也是可以的,之前我们有讲过调用function调用静态方法,如此一来我们也可以通过全局变量来定义了
下面我们就要说一下这里面比较难理解的这一块,关于集合内容的类型说明,
对于集合中放的value,我们可以通过源码得知,SetGlobal其实是放的Object,所以在规则文件中,读取的也是Object,所以我们定义的值,或者是泛型都要通过强转才能将值取出。
在定义global时要注意,因为我们知道,global是不会放到工作内存中的,但是如果我们在定义时,有两个规则文件中的都用到了同一个全局变量,我们会发现,这两个global 的内容不会因为其他调用的改变而改变。
得出的结论就是,global 不是用来做数据共享的,session会影响到global的用法。
我们在使用全局变量时要特别注意一下:
1、常量值是不能改变的
2、包装类是不能改变的
3、类似javaBean这样的操作,是可以改变内容的,但内存地址不会变
原创文章,作者:ItWorker,如若转载,请注明出处:https://blog.ytso.com/15233.html