0
点赞
收藏
分享

微信扫一扫

一种应用drools引擎驱动订单流程的方式

正义的杰克船长 2022-03-12 阅读 117

1.Drools规则引擎简介

2.Drools规则引擎基本语法

Drools 规则引擎中,标准的规则文件就是以“ drl ”结尾的文本文件,由于它是标准的文本文件,因此可以通过一些记事本工具对其进行査阅和编辑,也可以存储在数据库中。规则内容是放在规则文件中的,一个规则文件可以存放多个规则体。除此之外,规则文件还可以存放用户自定义的函数、数据对象及自定义査询等。

一套完整的规则文件内容如表2-1所示。

表2-1:一套完整的规则文件内容
关键字描述
package包名,只限于逻辑上的管理,若自定义的查询或函数位于同一包名,不管物理位
import规则引用问题,导入类或方法
global全局变量
function自定义函数
queries查询
rule end规则体,后续基本用到规则体中的特性

由于篇幅限制,仅介绍与系统应用到的重要关键字进行介绍。

package:除 package 之外,其他关键字在规则文件中的顺序是任意的,规则文件中必须要有一 个 package 声明,并且 package 声明要放在规则文件的第一行(规则模板”除外)。规则文件中的 package 和 Java 语言中的 package 有相似之处,不同的是在 Java 文件中 package 是用来把功能相似或相关的文件放在同一个 package 下进行管理。这种 package 管理既有物理上 Java 文件位置的管理,又有逻辑上文件位置的管理;在 Java 文件中通过 package 管理文件要求文件位置在逻辑上与物理上都要保持一致。在 Drools 规则引擎的规则文件中, package 对于规则文件中规则的管理只限于逻辑上的管理,并不管规则文件所在的物理目录,这是规则文件与 Java 类文件中 package 的区别。
同一个 package 下,用户可以自定义函数、自定义查询等,不管这些函数与查询是否在同一个规则文件中,都是可以直接使用的,这与 Java 中同一 package 的 Java 类调用相似。

rule end :规则内容中的规则体,是进行业务规则判断、处理业务结果的部分。规则体语法结构如表2-2所示。

表2-2 规则体语法结构
关键字描述
rule规则开始,参数是规则的唯一名称
attributes规则属性,是rule和when之间的参数,为可选项
when规则条件部分,决定then部分是否执行
then规则结果部分
end规则结束

在订单流程系统中,关键配置信息为when部分,该部分由具体业务人员配置具体业务规则确定。

单个drl规则示例:

rule "test-pattern-rule"

when

then
    System.out.println("规则被触发");
 end

 具体的业务执行中,then语句会替换成具体的Java执行接口,如视图接口以及业务方法等。

3.多个规则执行控制

上述章节已经展示了单个规则是如何执行的,但是订单的流程驱动中涉及到多个任务节点,并且节点与节点之间涉及到串行、并行、互斥等执行关系,势必会需要在规则与规则之间做出逻辑控制。

串行:多个规则执行文件默认由上至下执行,天然具有串行执行特点。

互斥:使用drools关键字 "activation-group",该属性特点是:激活分组,通过字符串定义分组名称,具有相同组名称的规则体只有一个规则被激活,其他的规则即使为true,也不会进行执行,达成互斥目的。

String activicationName = "activation-group " + "\"" + "mutualGroup" + "\"";

并行:由于drools规则引擎没有自带并行执行特性,这部分内容通过自研java开发实现,配置为并发标记的节点携带的规则,单独由一个规则文件进行承载。以下为并行组件的部分源码:

for (Object object : jsonArray) {
            JSONObject jsonObject = (JSONObject) object;
            String key = jsonObject.getString("id");
            String parallelRuleBody = ruleService.findById(jsonObject.getString("code")).getDroolsRule();
            String ruleName = "rule " + "\"" + key + "\"" + " ";
            parallelRuleString = parallelRuleString + ruleName + parallelRuleBody + " ";
            if (jsonObject.containsKey("children")) {
                childrenTreeMap.put(key, jsonObject.getJSONArray("children"));
            }
        }
        KieBase kieBase = DroolsUtil.getKieBase(parallelRuleString);
        List <Future<Exception>> list = new LinkedList <>();
        for (Object object : jsonArray) {
            try {
                Future <Exception> future = cs.submit(new Callable <Exception>() {
                    @Override
                    public WaitException call() throws WaitException {
                        try {
                            JSONObject jsonObject = (JSONObject) object;
                            String key = jsonObject.getString("id");
                            reloadService.runChildrenTree(kieBase, childrenTreeMap, flowInstId, key, dataId, flowCode);
                            return null;
                        } catch (WaitException e) {
                            return new WaitException();
                        }
                    }
                });
                list.add(future);
            } catch (WaitException e) {
               
            }
        }

以上举例订单中心实现的最基本的流程控制规则,限于篇幅,一些实现的复杂特性不再赘述。

4、整合Springboot以及整体实现流程

首先在pom文件中添加drools依赖:

		<dependency>
			<groupId>org.drools</groupId>
			<artifactId>drools-compiler</artifactId>
			<version>${drools.version}</version>
		</dependency>

以及单个规则执行的样例代码:

		KieBase kieBase = DroolsUtil.getKieBase(ruleString);
		long dataIdL = Long.parseLong(dataId);
		JSONObject orderData = orderProviderConsumerService.getOrderDataById(dataIdL);
		KieSession session = kieBase.newKieSession();
		try {
			session.addEventListener(new RuleFireListener());
			session.setGlobal("orderData", orderData);
			// 设置全局变量
			session.setGlobal("nodeChildrenMap", jsonMap);
			// 传入流程实例Id
			session.setGlobal("flowInstId", flowId);
			session.setGlobal("orderId", dataId);
			session.setGlobal("flowCode", flowCode);
			session.fireAllRules();
		}finally {
			session.dispose();
		}

在每个控制节点从数据库获得配置规则数据组装成规则文件后,通过上述代码执行相应规则。

其中orderData是传入规则中的全局变量,因为规则执行的元数据来自于订单数据。具体的路径也由此传入。

                                                              图4-1 流程启动流程图

 

举报

相关推荐

0 条评论