1.练习目标
使用Drools Workbench集中管理規則
应用程序中调用Drools Workbench中的规则文件执行
Drools Workbench中的规则升级时,程序可以自动获取到最新版本的规则投入使用--不用重启应用
在Drools Workbench中模拟数据测试规则
2.练习内容
练习的业务场景模拟来源自Drools官方文档中的一个人员申请驾照的案例,规则约束如下
3.练习步骤
3.1在Drools Workbench中新建项目
输入要建立的项目基本信息
group ID:com.pachiraframework
artifact ID:driving-license
version:1.0
项目名称:驾照申请程序
项目描述:该项目的一些描述信息
创建成后,项目列表中能就会出现刚添加过的项目了
3.2Drools Workbench中新建FactType对象 Applicant
对于这个场景而说,只有一个Fact对象,就是Applicant(申请人),它包含如下几个基本属性
String name;//申请人姓名
int age;//年龄
boolean valid;//是否可以申请
点击工程列表中的工程名字的链接,进入工程组件页面,点击如下的按钮,创建一个drl文件
选择要创建的Fact所在的包和文件名称
这里的包我们选择com.pachiraframework.driving_license
名称:Applicant
使用域专用语言:不勾选
创建成功后就会到如下的页面上
可以看到创建成的是一个只含有package定义的空的drl文件,接下来我们对Applicant进行建模
添加完成后,点击保存,这个时候Drools Workbench将使用git作为版本管理工具生成文件的更改历史记录信息
3.3Drools Workbench中新建申请规则
新建一个drl文件,名称为【驾照申请规则定义】,注意包的选择要和上个步骤中的Applicant在同一个包下
规则的内容如下,注意,在规则中使用到了上个步骤中定义的Applicant
编写完成后,可以点击一下右侧的【验证】链接校验一下规则是否有问题
验证无误后,点击【保存】按钮,记录规则改动信息到版本控制系统中(git)
通过如上步骤规则已经编写完毕,可以将规则发布了,首先进入到项目的主页上,然后点击右侧的【Build & Deploy】按钮
构建成功提示出现后,点击如下的链接去查看下发布好的jar包
注意gav列的内容都是undetermined,这个初步断定是drools7.1以后版本后的一个bug,只是在这个地方展示的时候不对,但是并不影响后续的程序开发使用
3.6Eclipse中新建driving程序调用规则
pom.xml文件定义
在pom.xml中增加Drools Workbench内嵌的Maven的repository
pom.xml中增加log日志logback的定义
注意一定要加入kie-cli的应用,这个jar包将会用来自动扫描Drools Workbench中发布的最新规则jar包版本并下载到本地
4.0.0
com.pachiraframework
driving
0.0.1-SNAPSHOT
jar
driving
http://maven.apache.org
UTF-8
7.2.0.Final
org.kie
kie-bom
pom
${drools.version}
import
junit
junit
4.12
test
org.kie
kie-api
org.kie
kie-ci
${drools.version}
org.slf4j
slf4j-api
1.7.7
ch.qos.logback
logback-classic
1.1.2
ch.qos.logback
logback-core
1.1.2
org.apache.maven.plugins
maven-compiler-plugin
3.5.1
1.8
1.8
guvnor-m2-repo
Guvnor M2 Repo
http://localhost:8080/kie-drools-wb/maven2/
打开${user.home}/.m2/settings.xml文件
增加Drools Workbench私服的登录帐号
为了查看drools框架的启动日志,可以将日志级别调到info,在src/main/resources目录下新增logback.xml文件,内容如下
%d{HH:mm:ss.SSS} [%thread] %-5level %logger - %msg%n
package com.pachiraframework.driving;
import org.drools.compiler.kproject.ReleaseIdImpl;
import org.kie.api.KieBase;
import org.kie.api.KieServices;
import org.kie.api.builder.KieScanner;
import org.kie.api.definition.type.FactType;
import org.kie.api.runtime.KieContainer;
import org.kie.api.runtime.StatelessKieSession;
/**
* Hello world!
*
*/
public class App {
public static void main(String[] args) throws Exception{
ReleaseIdImpl releaseId = new ReleaseIdImpl("com.pachiraframework","driving-license","LATEST");
KieServices ks = KieServices.Factory.get();
KieContainer container = ks.newKieContainer(releaseId);
KieScanner scanner = ks.newKieScanner(container);
scanner.start(1000);
StatelessKieSession session = container.newStatelessKieSession();
for(int i = 0;i < 100;i++) {
FactType factType = factType(container.getKieBase());
Object applicant = makeApplicant(factType);
session.execute(applicant);
System.out.println("申请人:"+factType.get(applicant, "name")+",年龄:"+factType.get(applicant, "age")+"是否可以申请驾照"+factType.get(applicant, "valid"));
Thread.sleep(20000);//休眠20秒,等待更新规则查看输出结果
}
}
private static Object makeApplicant(FactType factType) throws Exception{
Object applicant = factType.newInstance();
factType.set(applicant, "name", "张三");
factType.set(applicant, "age", 17);
return applicant;
}
protected static FactType factType(KieBase base) {
FactType factType = base.getFactType("com.pachiraframework.driving_license", "Applicant");
return factType;
}
}
由于规则是通过Drools Workbench定义在远程服务器上的,因此应用程序需要配置该规则对应jar包的GAV信息,配置了LASTEST版本,就是要去获取服务器上最新 版本的jar
那程序是怎么知道去Drools Workbench在哪儿呢?就是通过在pom.xml中定义的
启动一个定时器定期去Drools Workbench上检查规则包是否有最新版本更新发布,如果有,则该定时器会负责将最新规则包拉取到本地,并使最新规则生效(后台线程运行)
在这个例子中,规则定义是接收Applicant类型的参数的,而Eclipse工程中并没有这个类的定义,这个时候可以通过类似反射的机制,来根据在Drools Workbench中定义的Applicant的包名和名称将其对应的类型对象生成出来
通过类似反射机制,对Applicant对象的各个属性进行赋值
代码示例中,传递的是一个年龄是17,valid=true的申请人信息
执行规则,按照规则定义,18岁以下禁止申请,规则中会把valid设置成false,通过这个代码块,将规则执行后的结果打印出来
通过执行结果可以看到,规则被执行了,申请人不满足申请条件,被拒绝了
3.7Drools Workbench中更新规则并发布
在代码块E的下方增加了一个Thread.sleep()函数,主要是每次循环执行完后休眠一段时间,在这段休眠的时间段内,我们可以在Drools Workbench中修改规则并发布一个新的版本,被Scanner定时器拉到本地,当sleep结束进入下次执行周期的时候,就能看到最新的规则执行了
在这个案例中,我们将驾照的申请规则从18岁调整成了16岁,并加了一行打印#的提示信息
特别注意:当修改了规则内容的时候,记得一定要升级项目工程的版本号,从而达到追踪项目jar包版本,以及保证已经依赖当前版本的程序不受更新影响的目的(有些工程可能明确的指定依赖具体的某个版本的jar,而不是每次取最新的)
在项目的首页上点击【Settings】按钮
进入版本配置页面,将项目升一个版本,这里,我们从1.0升级到了1.1,如图
保存修改并重新【Build & Deploy】
3.8Eclipse工程中验证调用最新规则的执行情况
4.总结
Drools Workbench内置了一个maven私服管理组件(简单)和一个git版本管理组件(简单)
内嵌的私服用于管理通过【Build & Deploy】发布的不同GAV的规则包
内嵌的git仅仅用来管理每次修改的变更记录(类似git每次提交都要写一个备注)
内置私服的仓库路径位于$CATALINA_HOME/bin/repositories/kie/global下
内置的git仓库位于$CATALINA_HOME/bin/.niogit目录下
每次对规进行修改发布的时候必须要升级项目的版本号
kie-cli组件会根据当前eclipse工程的pom.xml文件中定义的repository和settings.xml文件中定义的username password去Drools Workbench中拉取最新jar包
即使在Drools Workbench中通过declare方式来声明FactType,但是在【Build & Deploy】的时候该declare会被转换成对应的.class对象(可以查看本地.m2目录下拉取过来的最新的规则ar中的文件)
5.问题
将Applicant在Drools Workbench中进行定义(定义成java模型或者declare是一样的),那么在使用规则的系统中只能通过反射的方法(FactType factype= xxx),这样就有一些冗长的代码出现;而如果将Applicant定义在工程里,只在Drools Workbench中定义规则,那么每次又需要在Drools Workbench中导入Applicant的引入(jar包依赖),否则在Drools Workbench上是无法进行验证的,而且当Applicant的属性需要变化时,由于它和代码工程绑定在一起的,这样就失去了Drools Workbench进行远程集中管理的意义了,如何平衡这个矛盾?