drools规则语法-API与FACT(三)

在 Drools 当中,规则的编译与运行要通过Drools 提供的各种API 来实现,这些API 总体来讲可以分为三类:规则编译、规则收集和规则的执行。完成这些工作的API 主要有KnowledgeBuilder、KnowledgeBase、StatefulKnowledgeSession、StatelessKnowledgeSession、、等,它们起到了对规则文件进行收集、编译、查错、插入fact、设置global、执行规则或规则流等作用:
1 KnowledgeBuilder
     KnowledgeBuilder 的作用就是用来在业务代码当中收集已经编写好的规则, 然后对这些规则文件进行编译, 最终产生一批编译好的规则包(KnowledgePackage)给其它的应用程序使用。KnowledgeBuilder 在编译规则的时候可以通过其提供的hasErrors()方法得到编译规则过程中发现规则是否有错误,如果有的话通过其提供的getErrors()方法将错误打印出来,以帮助我们找到规则当中的错误信息。创建KnowledgeBuilder 对象使用的是KnowledgeBuilderFactory 的newKnowledgeBuilder方法,实例如下:
import java.util.Collection;
import org.drools.builder.KnowledgeBuilder;
import org.drools.builder.KnowledgeBuilderFactory;
import org.drools.builder.ResourceType;
import org.drools.definition.KnowledgePackage;
import org.drools.io.ResourceFactory;
public class Test {
public static void main(String[] args) {
KnowledgeBuilder
kbuilder=KnowledgeBuilderFactory.newKnowledgeBuilder();
kbuilder.add(ResourceFactory.newClassPathResource("test.drl",
Test.class),ResourceType.DRL);
Collection<KnowledgePackage>
kpackage=kbuilder.getKnowledgePackages();//产生规则包的集合
    }
}

      通过KnowledgeBuilder 编译的规则文件的类型可以有很多种,如.drl 文件、.dslr 文件或一个xls 文件等。产生的规则包可以是具体的规则文件形成的,也可以是规则流(rule flow)文件形成的,在添加规则文件时,需要通过使用 ResourceType 的枚举值来指定规则文件的类型;同时在指定规则文件的时候drools 还提供了一个名为                   ResourceFactory 的对象,通过该对象可以实现从Classpath、URL、File、ByteArray、Reader 或诸如XLS 的二进制文件里添加载规则。

2 KnowledgeBase

     KnowledgeBase 是 Drools 提供的用来收集应用当中知识(knowledge)定义的知识库对象,在一个KnowledgeBase 当中可以包含普通的规则(rule)、规则流(rule flow)、函数定义(function)、用户自定义对象(type model)等。KnowledgeBase 本身不包含任何业务数据对象(fact 对象,后面有相应章节着重介绍fact 对象),业务对象都是插入到由KnowledgeBase产生的两种类型的session 对象当中(StatefulKnowledgeSession 和StatelessKnowledgeSession,后面会有对应的章节对这两种类型的对象进行介绍),通过session 对象可以触发规则执行或开始一个规则流执行。创建一个KnowledgeBase 要通过KnowledgeBaseFactory 对象提供的newKnowledgeBase()方法来实现,这其中创建的时候还可以为其指定一个KnowledgeBaseConfiguration 对象,KnowledgeBaseConfiguration 对象是一个用来存放规则引擎运行时相关环境参数定义的配置对象
public class Test {
public static void main(String[] args) {
KnowledgeBaseConfiguration kbConf =
KnowledgeBaseFactory.newKnowledgeBaseConfiguration();
kbConf.setProperty( "org.drools.sequential", "true");
KnowledgeBase kbase =
KnowledgeBaseFactory.newKnowledgeBase(kbConf);
   }
}
      创建一个KnowledgeBaseConfiguration 对象的方法也是使用KnowldegeBaseFactory,使用的是其提供的newKnowledgeBaseConfiguration()方法,该方法创建好的KnowledgeBaseConfiguration 对象默认情况下会加载drools-core-5.0.1.jar 包下META-INF/drools.default.rulebase.conf 文件里的规则运行环境配置信息,加载完成后,我们可以在代码中对这些默认的信息重新赋值,以覆盖加载的默认值,比如这里我们就把org.drools.sequential 的值修改为true,它的默认值为false。除了这种方式创建KnowledgeBaseConfiguration 方法之外,我们还可以为其显示的指定一个Properties 对象,在该对象中设置好需要覆盖默认值的相关属性的值,然后再通过newKnowledgeBaseConfiguration(Properties prop , ClassLoader loader) 方法创建一个KnowledgeBaseConfiguration 对象。该方法方法当中第一个参数就是我们要设置的Properties对象,第二个参数用来设置加载META-INF/drools.default.rulebase.conf 文件的ClassLoader,因为该文件在ClassPath 下,所以采用的是ClassLoader 方法进行加载,如果不指定这个参数,那么就取默认的ClassLoader 对象, 如果两个参数都为null , 那么就和newKnowledgeBaseConfiguration()方法的作用相同了。示例如下:
用来设置默认规则运行环境文件drools.default.rulebase.conf 里面所涉及到的具体项内容

drools.maintainTms = <true|false>
drools.assertBehaviour = <identity|equality>
drools.logicalOverride = <discard|preserve>
drools.sequential = <true|false>
drools.sequential.agenda = <sequential|dynamic>
drools.removeIdentities = <true|false>
drools.shareAlphaNodes = <true|false>
drools.shareBetaNodes = <true|false>
drools.alphaNodeHashingThreshold = <1...n>
drools.compositeKeyDepth = <1..3>
drools.indexLeftBetaMemory = <true/false>
drools.indexRightBetaMemory = <true/false>
drools.consequenceExceptionHandler = <qualified class name>
drools.maxThreads = <-1|1..n>
drools.multithreadEvaluation = <true|false>


KnowledgeBase 创建完成之后,接下来就可以将我们前面使用KnowledgeBuilder 生成的KnowledgePackage 的集合添加到KnowledgeBase 当中,以备使用:
public class Test {
public static void main(String[] args) {
KnowledgeBuilder kbuilder = KnowledgeBuilderFactory
.newKnowledgeBuilder();
kbuilder.add(ResourceFactory.newClassPathResource("test.drl",Test.class), ResourceType.DRL);
Collection<KnowledgePackage> kpackage =
kbuilder.getKnowledgePackages();
KnowledgeBaseConfiguration kbConf = KnowledgeBaseFactory
.newKnowledgeBaseConfiguration();
kbConf.setProperty("org.drools.sequential", "true");
KnowledgeBase kbase =
KnowledgeBaseFactory.newKnowledgeBase(kbConf);
kbase.addKnowledgePackages(kpackage);//将KnowledgePackage集合添加到KnowledgeBase当中
 }
}
3 StatefulKnowledgeSessions
       StatefulKnowledgeSession 对象是一种最常用的与规则引擎进行交互的方式,它可以与规则引擎建立一个持续的交互通道,在推理计算的过程当中可能会多次触发同一数据集。在用户的代码当中,最后使用完StatefulKnowledgeSession 对象之后,一定要调用其dispose()方法以释放相关内存资源。
       StatefulKnowledgeSession 可以接受外部插入(insert)的业务数据——也叫fact,一个fact 对象通常是一个普通的Java 的POJO,一般它们会有若干个属性,每一个属性都会对应getter 和setter 方法,用来对外提供数据的设置与访问。一般来说,在Drools 规则引擎当中,fact 所承担的作用就是将规则当中要用到的业务数据从应用当中传入进来,对于规则当中产生的数据及状态的变化通常不用fact 传出。如果在规则当中需要有数据传出,那么可以通过在StatefulKnowledgeSession 当中设置global 对象来实现,一个global 对象也是一个普通的Java 对象,在向StatefulKnowledgeSession 当中设置global 对象时不用insert 方法而用setGlobal 方法实现。
创建一个StatefulKnowledgeSession 要通过KnowledgeBase 对象来实现,示例如下:

public class Test {
public static void main(String[] args) {
KnowledgeBuilder kbuilder = KnowledgeBuilderFactory
.newKnowledgeBuilder();
kbuilder.add(ResourceFactory.newClassPathResource("test.drl",
Test.class), ResourceType.DRL);
Collection<KnowledgePackage> kpackage =
kbuilder.getKnowledgePackages();
KnowledgeBaseConfiguration kbConf = KnowledgeBaseFactory
.newKnowledgeBaseConfiguration();
kbConf.setProperty("org.drools.sequential", "true");
KnowledgeBase kbase =
KnowledgeBaseFactory.newKnowledgeBase(kbConf);
kbase.addKnowledgePackages(kpackage);//将KnowledgePackage集合添加到KnowledgeBase当中
StatefulKnowledgeSession
statefulKSession=kbase.newStatefulKnowledgeSession();
statefulKSession.setGlobal("globalTest", new Object());//设置一个global对象
statefulKSession.insert(new Object());//插入一个fact对象
statefulKSession.fireAllRules();
statefulKSession.dispose();
  }
}
4 StateLessKnowledgeSession
       StatelessKnowledgeSession 的作用与StatefulKnowledgeSession 相仿,它们都是用来接收业务数据、执行规则的。事实上,StatelessKnowledgeSession 对StatefulKnowledgeSession 做了包装,使得在使用StatelessKnowledgeSession 对象时不需要再调用dispose()方法释放内存资源了。
因为StatelessKnowledgeSession 本身所具有的一些特性,决定了它的使用有一定的局限性。在使用StatelessKnowledgeSession 时不能进行重复插入fact 的操作、也不能重复的调用fireAllRules()方法来执行所有的规则,对应这些要完成的工作在StatelessKnowledgeSession当中只有execute(…)方法,通过这个方法可以实现插入所有的fact 并且可以同时执行所有的规则或规则流,事实上也就是在执行execute(…)方法的时候就在StatelessKnowledgeSession内部执行了insert()方法、fireAllRules()方法和dispose()方法。示例如下:

StatelessKnowledgeSession
statelessKSession=kbase.newStatelessKnowledgeSession();
ArrayList list=new ArrayList();
list.add(new Object());
list.add(new Object());
statelessKSession.execute(list);
       如果我们要插入的fact 就是这个ArrayList 而不是它内部的Element那该怎么做呢?在StatelessKnowledgeSession 当中,还提供了execute(Command cmd)的方法,在该方法中通过CommandFactory 可以创建各种类型的Command,比如前面的需求要直接将这个ArrayList 作为一个fact 插入,那么就可以采用CommandFactory.newInsert(Object obj)来实现:
statelessKSession.execute(CommandFactory.newInsert(list));
如 果需要通过StatelessKnowledgeSession 设置global 的话, 可以使用CommandFactory.newSetGlobal(“key”,Object obj)来实现;如果即要插入若干个fact,又要设置相关的global,那么可以将CommandFactory 产生的Command 对象放在一个Collection 当中,然后再通过CommandFactory.newBatchExecution(Collection collection)方法实现.

二FACT对象
        Fact 是指在Drools 规则应用当中,将一个普通的JavaBean 插入到规则的WorkingMemory当中后的对象。规则可以对Fact 对象进行任意的读写操作,当一个JavaBean 插入到WorkingMemory 当中变成Fact 之后,Fact 对象不是对原来的JavaBean 对象进行Clon,而是原来JavaBean 对象的引用。规则在进行计算的时候需要用到应用系统当中的数据,这些数据设置在Fact 对象当中,然后将其插入到规则的WorkingMemory 当中,这样在规则当中就可以通过对Fact 对象数据的读写,从而实现对应用数据的读写操作。一个Fact 对象通常是一个具有getter 和setter 方法的POJO 对象,通过这些getter 和setter 方法可以方便的实现对Fact 对象的读写操作,所以我们可以简单的把Fact 对象理解为规则与应用系统数据交互的桥梁或通道。
       当 Fact 对象插入到WorkingMemory 当中后,会与当前WorkingMemory 当中所有的规则进行匹配,同时返回一个FactHandler 对象。FactHandler 对象是插入到WorkingMemory当中Fact 对象的引用句柄,通过FactHandler 对象可以实现对对应的Fact 对象的删除及修改等操作。
在前面介绍StatefulKnowledgeSession 和StatelessKnowledgeSession 两个对象的时候也提到了插入Fact 对象的方法,在StatefulKnowledgeSession 当中直接使用insert 方法就可以将一个Java 对象插入到WokingMemory 当中,如果有多个Fact 需要插入,那么多个调用insert方法即可;对于StatelessKnowledgeSession 对象可利用CommandFactory 实现单个Fact 对象或多个Fact 对象的插入。


评论 12
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值