欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

SpringBoot配合Drools workbench(BusinessCentral)和maven配置实现动态规则更新

程序员文章站 2022-05-28 11:18:46
...

遇到的困境

如前面的博文《Docker安装drools workbench和kie-server,使用http调用kie-server rest接口传json参数跑规则》所述,折腾了老半天,装好了workbench,终于可以编辑规则了。也配置好了kie server,终于可以动态发布规则了。然而还是遇到点问题:

  1. 引入一个kieServer又增加了开发和运维的负担,一个workbench已经够复杂了;
  2. 使用Kie server提供的rest api,功能限制很多,比如我最需要的,过滤指定规则名, 就无法支持;
  3. 若使用java api,规则名到是可以过滤了,那么就会遇到另一个问题:规则中使用到的数据对象,实际上是一个java bean, 在insert之前,是需要我们自己初始化的。比如,我们定义这么一个简单规则
import com.myspace.INPUTDATA;
import com.myspace.OUTPUTDATA;

//节点1
rule "DD_1"
	dialect "mvel"
	lock-on-active true
	when
		$p:INPUTDATA(currentNode=="1")
	$rsp: OUTPUTDATA()
	then
		$rsp.nodeCode = "2.1";
end

规则中,会对插入对象进行判断,那么我们要如何触发这个规则呢,如下:

com.myspace.INPUTDATA obj = new com.myspace.INPUTDATA();
com.myspace.OUTPUTDATA rsp = new com.myspace.OUTPUTDATA();
//...赋值
session.insert(obj);
session.insert(rsp);
// 执行规则
session.fireAllRules();
// session释放资源
session.dispose();

看到问题了吗,我们在java代码里面,需要初始化数据对象,而这个数据对象,在使用场景中,很可能是由业务人员在workbench中自己定义的,并且可能随时变化。

在网上大多数例子中,作者会告诉大家,需要在你的工程本地按照相同的包名、类名、属性新建一个对应的java类,只有这样才能正确地调用规则。

我也和部分使用者进行了讨论,并得出一个结论-“数据对象应该是不易变化的,变化的是对数据对象进行判断和操作对规则”。所以这种使用模式并不应该成为困扰。

但我并不满足,只怕业务也很难接受,他需要提前定义好可能用到的数据对象,若需要增改属性,还得重新发布服务。而在我们的实际使用场景中,属性的变化是比较频繁的。

解决的思路

再梳理一下,我们的需求其实很简单,就是监听workbench发布的新规则包(业务强烈要求可视化配置页面,否则workbench都可以省掉了),然后加载到内存,对外提供http json接口调用即可。至于额外的什么日志、负载…用SpringBoot不香吗?

于是打算这么做:

  1. 使用SpringBoot搭建一个架子
  2. 启动时通过配置文件去拉取指定的kjar文件(使用workbench发布),并加载成规则包
  3. 监听规则包变化,若有新的规则包,自动更新
  4. 将json请求反射构造成数据对象,转为对drools的java api调用,再将规则执行结果序列化成json字符串返回调用端

关键的节点

拉取

怎么用SpringBoot搭个架子就不赘述了,我们需要做的是,启动的时候去拉取指定的kjar文件,并保持监听。

而这实际上是drools早就支持的功能,只需要简单几行代码如下:

KieServices kieServices = KieServices.Factory.get();

UrlResource resource = (UrlResource) kieServices.getResources().newUrlResource(url);
//访问workbench所需要的登录账户信息
resource.setUsername(workBenchName);
resource.setPassword(workBenchPassword);
resource.setBasicAuthentication("enabled");

InputStream inputStream = resource.getInputStream();

KieRepository repository = kieServices.getRepository();
KieModule kieModule = repository.addKieModule(kieServices.getResources().newInputStreamResource(inputStream));
this.kieContainer = kieServices.newKieContainer(kieModule.getReleaseId());

其中url即为在workbench上发布的规则包下载地址。

监听

版本

反射

坑爹的细节

没有外网的环境下部署

Maven配置导致的401错误

优化

尾声