Drools 文档(构建)

介绍

6.0引入了一种新的配置和约定方法来构建知识库,而不是在5.x中使用编程构建器方法,构建器仍然可使用,由于它用于工具集成。编程

构建如今使用Maven,并与Maven实践保持一致,KIE项目或模块只是一个Maven Java项目或模块,另外还有一个元数据文件META-INF/kmodule.xml,kmodule.xml文件是选择资源到知识库并配置这些知识库和会话的描述符,还有经过Spring和OSGi蓝图提供的XML支持。api

虽然标准Maven能够构建和打包KIE资源,但它不会在构建时提供验证,有一个Maven插件,推荐使用它来得到构建时验证,插件还生成许多类,使运行时加载速度更快。缓存

示例项目布局和Maven POM描述符在屏幕截图中进行了说明:session

defaultkiesession.png

KIE使用默认值来最小化配置的数量,一个空的kmodule.xml是最简单的配置,必须始终有一个kmodule.xml文件,即便是空的,由于它用于发现JAR及其内容。less

Maven能够经过“mvn install”将一个KieModule部署到本地机器上,本地机器上的全部其余应用程序都使用它,或者它能够“mvn deploy”将KieModule推到远程Maven存储库中,构建应用程序将拉取KieModule并在过程当中填充本地Maven存储库。dom

maven.png

JAR能够以两种方式部署,要么像Maven依赖项清单中的其余JAR同样添加到类路径,要么在运行时动态加载它们,KIE将扫描类路径以找到全部包含kmodule.xml的jar文件,每一个发现的JAR都由KieModule接口表示。术语类路径KieModule和动态KieModule用于引用这两种加载方法,虽然动态模块支持并行版本控制,可是类路径模块不支持,此外,一旦模块在类路径上,就不能动态加载其余版本。maven

API的详细参考资料将包含在下一节中,没有耐心的人能够直接跳转到示例部分,这对于不一样的用例来讲是至关容易理解的。ide

构建

builder.png

建立和构建一个Kie项目

Kie项目具备普通Maven项目的结构,惟一的特色是包含kmodule.xml文件,以声明的方式定义能够从中建立的KieBaseKieSession,这个文件必须放在Maven项目的resources/META-INF文件夹中,而全部其余Kie工件,如DRL或Excel文件,必须存储在resources文件夹中或其下的任何其余子文件夹中。函数

因为全部配置方面都提供了有意义的默认值,因此最简单的kmodule.xml文件能够仅包含一个空的kmodule标记,以下所示:工具

<?xml version="1.0" encoding="UTF-8"?>
<kmodule xmlns="http://www.drools.org/xsd/kmodule"/>

这样,kmodule将包含一个默认的KieBase,存储在resources文件夹或其任何子文件夹下的全部Kie资源都将被编译并添加到其中,为了触发这些工件的构建,为它们建立一个KieContainer就足够了。

KieContainer.png

对于这个简单的例子,建立一个KieContainer就足够了,它能够读取从类路径构建的文件:

KieServices kieServices = KieServices.Factory.get();
KieContainer kContainer = kieServices.getKieClasspathContainer();

KieServices是一个能够访问全部Kie构建和运行时设施的接口:

KieServices.png

经过这种方式,全部Java源和Kie资源都被编译并部署到KieContainer中,而KieContainer使其内容在运行时可用。

kmodule.xml文件

如前一节所述,kmodule.xml文件是能够声明地配置能够从KIE项目建立的KieBaseKieSession的地方。

特别是KieBase是应用程序全部知识定义的存储库,它将包含规则、流程、函数和类型模型。KieBase自己不包含数据,相反,会话是从KieBase建立的,KieBase中能够插入数据,从KieBase中能够启动流程实例。建立KieBase可能很重,而建立会话很是轻,所以建议在可能的状况下缓存KieBase,以容许重复建立会话。然而,终端用户一般没必要担忧,由于KieContainer已经自动提供了这种缓存机制。

KieBase.png

相反,KieSession存储并在运行时数据上执行,它是由KieBase建立的,若是在kmodule.xml文件中定义了它,则更容易从KieContainer直接建立。

KieSession.png

kmodule.xml容许定义和配置一个或多个KieBase,并为每一个KieBase建立全部不一样的KieSession,以下面的示例所示:

<kmodule xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xmlns="http://www.drools.org/xsd/kmodule">
  <configuration>
    <property key="drools.evaluator.supersetOf" value="org.mycompany.SupersetOfEvaluatorDefinition"/>
  </configuration>
  <kbase name="KBase1" default="true" eventProcessingMode="cloud" equalsBehavior="equality" declarativeAgenda="enabled" packages="org.domain.pkg1">
    <ksession name="KSession2_1" type="stateful" default="true"/>
    <ksession name="KSession2_2" type="stateless" default="false" beliefSystem="jtms"/>
  </kbase>
  <kbase name="KBase2" default="false" eventProcessingMode="stream" equalsBehavior="equality" declarativeAgenda="enabled" packages="org.domain.pkg2, org.domain.pkg3" includes="KBase1">
    <ksession name="KSession3_1" type="stateful" default="false" clockType="realtime">
      <fileLogger file="drools.log" threaded="true" interval="10"/>
      <workItemHandlers>
        <workItemHandler name="name" type="org.domain.WorkItemHandler"/>
      </workItemHandlers>
      <listeners>
        <ruleRuntimeEventListener type="org.domain.RuleRuntimeListener"/>
        <agendaEventListener type="org.domain.FirstAgendaListener"/>
        <agendaEventListener type="org.domain.SecondAgendaListener"/>
        <processEventListener type="org.domain.ProcessListener"/>
      </listeners>
    </ksession>
  </kbase>
</kmodule>

在这里的标签包含一个键-值对列表,这些键-值对是用于配置KieBase构建过程的可选属性,例如,这个样例kmodule.xml文件定义了一个额外的自定义操做符,名为supersetOf,并由org.mycompany.SupersetOfEvaluatorDefinition类实现。

在定义了这两个KieBase以后,就能够从第一个KieBase中实例化两个不一样类型的KieSession,而从第二个KieBase中实例化一个,能够在kbase标记上定义的属性列表,以及它们的含义和默认值以下:

属性名称 默认值 承认的值 含义
name none 任何值 从KieContainer检索此KieBase的名称,这是惟一的强制属性。
includes none 任何逗号分隔的列表 这个kmodule中包含的其余KieBase的逗号分隔列表,全部这些KieBase的构件也将包括在这。
packages all 任何逗号分隔的列表 默认状况下,resources文件夹下的全部Drools构件(任何级别)都包含在KieBase中,此属性容许将在此KieBase中编译的构件限制为仅属于包列表的构件。
default false true,false 定义这个KieBase是不是这个模块的默认值,所以能够从KieContainer建立它,而不向它传递任何名称,每一个模块中最多能够有一个默认的KieBase。
equalsBehavior identity identity,equality 定义当一个新事实插入到工做内存中时,Drools的行为。使用identity,它老是建立一个新的FactHandle,除非同一个对象尚未出如今工做内存中,而只有在新插入的对象与已经存在的事实不相等(根据其相等的方法)时,它才相等。
eventProcessingMode cloud cloud,stream 在云模式下编译时,KieBase将事件视为正常事实,而在流模式下则容许对它们进行时间推理。
declarativeAgenda disabled disabled,enabled 定义声明性议程是否启用。

相似地,ksession标签的全部属性(固然名字除外)都有有意义的默认值,下表列出并描述了它们:

属性名称 默认值 承认的值 含义
name none 任何值 KieSession的惟一名称,用于从KieContainer提取KieSession,这是惟一的强制属性。
type stateful stateful,stateless 有状态会话容许迭代地使用工做内存,而无状态会话是使用提供的数据集一次性在工做内存中执行。
default false true,false 定义这个KieSession是不是这个模块的默认值,所以它能够从KieContainer建立,而无需传递任何名称,在每一个模块中,每种类型最多能够有一个默认的KieSession。
clockType realtime realtime,pseudo 定义事件时间戳是由系统时钟决定仍是由应用程序控制的psuedo时钟决定,这个时钟对于时间规则的单元测试特别有用。
beliefSystem simple simple,jtms,defeasible 定义KieSession所使用的信赖系统的类型。

正如前面的kmodule.xml示例所述,还能够在每一个KieSession上声明建立一个文件(或控制台)记录器、一个或多个WorkItemHandler和一些监听器,这些监听器能够是3种不一样的类型:ruleRuntimeEventListeneragendaEventListenerprocessEventListener

在定义了相似于前一个示例中的kmodule.xml以后,如今从KieContainer可使用它们的名称简单地检索KieBaseKieSession

KieServices kieServices = KieServices.Factory.get();
KieContainer kContainer = kieServices.getKieClasspathContainer();

KieBase kBase1 = kContainer.getKieBase("KBase1");
KieSession kieSession1 = kContainer.newKieSession("KSession2_1");
StatelessKieSession kieSession2 = kContainer.newStatelessKieSession("KSession2_2");

须要注意的是,因为KSession2_1KSession2_2属于两种不一样的类型(第一种是有状态的,而第二种是无状态的),所以须要根据KieContainer声明的类型调用两种不一样的方法。若是请求KieSessionKieContainer的类型与kmodule.xml文件中声明的类型不一致,KieContainer将抛出一个RuntimeException。另外,因为KieBaseKieSession已经被标记为default,因此在不传递任何名字的状况下,能够从KieContainer那里获得它们。

KieContainer kContainer = ...

KieBase kBase1 = kContainer.getKieBase(); // returns KBase1
KieSession kieSession1 = kContainer.newKieSession(); // returns KSession2_1

因为Kie项目也是Maven项目,所以在pom.xml文件中声明的groupId、artifactId和version用于生成一个ReleaseId,用于在应用程序中惟一标识该项目,这容许经过简单地将ReleaseId传递给KieServices来从项目中建立一个新的KieContainer

KieServices kieServices = KieServices.Factory.get();
ReleaseId releaseId = kieServices.newReleaseId( "org.acme", "myartifact", "1.0" );
KieContainer kieContainer = kieServices.newKieContainer( releaseId );

使用Maven构建

Maven的KIE插件确保构件资源获得验证和预编译,建议在任什么时候候都使用它,要使用该插件,只需将其添加到Maven pom的构建部分。xml并经过使用包装kjar激活它。要使用该插件,只需将其添加到Maven pom.xml的build部分,并经过使用打包kjar激活它。

<packaging>kjar</packaging>
  ...
  <build>
    <plugins>
      <plugin>
        <groupId>org.kie</groupId>
        <artifactId>kie-maven-plugin</artifactId>
        <version>7.7.0.Final</version>
        <extensions>true</extensions>
      </plugin>
    </plugins>
  </build>

这个插件支持全部Drools/jBPM knowledge资源。可是,若是你在Java类中使用特定的KIE注解,例如@kie.api.Position,你须要在kie-api上添加编译时依赖到你的项目。咱们建议对全部其余的KIE依赖项使用提供的做用域,这样,kjar就会尽量保持轻量级,而不依赖于任何特定的KIE版本。

在不使用Maven插件的状况下构建KIE模块将把全部资源复制到生成的JAR中,当运行时加载JAR时,它将尝试构建全部资源,若是存在编译问题,它将返回null KieContainer,它还将编译开销推到运行时,通常来讲,这是不推荐的,并且Maven插件应该老是被使用。

以编程方式定义KieModule

还能够经过编程方式定义属于KieModule的KieBaseKieSession,而不是kmodule.xml文件中的声明性定义。一样的编程API还容许显式地添加包含Kie构件的文件,而不是自动从项目的resources文件夹中读取它们。为此,有必要建立一个KieFileSystem(一种虚拟文件系统),并将项目中包含的全部资源添加到其中。

KieFileSystem.png

像全部其余Kie核心组件同样,你能够从KieServices得到KieFileSystem的实例,kmodule.xml配置文件必须添加到文件系统中,这是一个强制性的步骤。Kie还提供了一个由KieModuleModel实现的方便的fluent API,以编程方式建立这个文件。

KieModuleModel.png

为了在实践中作到这一点,有必要从KieServices中建立一个KieModuleModel,使用所需的KieBaseKieSession配置它,转换到XML,并将XML添加到KieFileSystem,这个过程以下例所示:

KieServices kieServices = KieServices.Factory.get();
KieModuleModel kieModuleModel = kieServices.newKieModuleModel();

KieBaseModel kieBaseModel1 = kieModuleModel.newKieBaseModel( "KBase1 ")
        .setDefault( true )
        .setEqualsBehavior( EqualityBehaviorOption.EQUALITY )
        .setEventProcessingMode( EventProcessingOption.STREAM );

KieSessionModel ksessionModel1 = kieBaseModel1.newKieSessionModel( "KSession1" )
        .setDefault( true )
        .setType( KieSessionModel.KieSessionType.STATEFUL )
        .setClockType( ClockTypeOption.get("realtime") );

KieFileSystem kfs = kieServices.newKieFileSystem();
kfs.writeKModuleXML(kieModuleModel.toXML());

此时,还须要经过它的fluent API向KieFileSystem添加其余全部构成项目的Kie构件,这些构件必须添加到相应的Maven项目的相同位置。

KieFileSystem kfs = ...
kfs.write( "src/main/resources/KBase1/ruleSet1.drl", stringContainingAValidDRL )
        .write( "src/main/resources/dtable.xls",
                kieServices.getResources().newInputStreamResource( dtableFileStream ) );

这个示例代表,添加Kie构件能够同时做为纯字符串和Resource,在后者中,Resource能够由KieResources工厂建立,也能够由KieServices提供,KieResources提供了许多方便的工厂方法来将InputStreamURLFile或表示文件系统路径的String转换为能够由KieFileSystem管理的Resource

KieResources.png

一般,能够从用于将Resource添加到KieFileSystem的名称的扩展推断出资源的类型,可是,也能够不遵循Kie约定的文件扩展名,并显式地为Resource分配特定的ResourceType,以下所示:

KieFileSystem kfs = ...
kfs.write( "src/main/resources/myDrl.txt",
           kieServices.getResources().newInputStreamResource( drlStream )
                      .setResourceType(ResourceType.DRL) );

将全部资源添加到KieFileSystem并经过将KieFileSystem传递给KieBuilder来构建它。

KieBuilder.png

当成功构建KieFileSystem的内容时,生成的KieModule会自动添加到KieRepositoryKieRepository是一个单例库,充当全部可用KieModule的存储库。

KieRepository.png

在此以后,就能够经过KieServicesKieModule建立一个新的KieContainer,使用ReleaseId,可是,由于在这种状况下,KieFileSystem并不包含任何pom.xml文件(可使用KieFileSystem.writePomXML方法添加xml文件),Kie不能肯定KieModuleReleaseId,并给它赋一个默认值,这个默认的ReleaseId能够从KieRepository得到,用来识别KieRepository内部的KieModule,下面的示例展现了整个过程。

KieServices kieServices = KieServices.Factory.get();
KieFileSystem kfs = ...
kieServices.newKieBuilder( kfs ).buildAll();
KieContainer kieContainer = kieServices.newKieContainer(kieServices.getRepository().getDefaultReleaseId());

在这一点上,能够从这个KieContainer得到KieBase并建立新的KieSession,这与直接从类路径建立KieContainer的状况彻底相同。

相关文章
相关标签/搜索