【Drools】(二)基于业务需求动态生成 DRL 规则文件:事实与动作定义详解

【Drools】(二)基于业务需求动态生成 DRL 规则文件:事实与动作定义详解

在现代业务规则管理系统中,灵活高效地生成和管理规则至关重要。通过上一部分的DRT 规则模板(请参考(一)基于业务需求动态生成 DRT 规则模板:事实与动作定义详解)结合业务上的动作定义和事实定义,自动生成 DRL(Drools Rule Language)规则文件,可以根据业务需求自定义和调整规则,从而提高业务的灵活性和响应速度。本文将详细介绍如何根据业务需求动态生成 DRL 规则文件,并结合示例界面图和代码进行说明。

drools介绍,请参考: 探索Drools:Java世界的规则引擎

图示示例说明

下图数据是根据事实定义和动作定义,自动初始化数据,业务人员可自行定义,主要包含了规则信息和规则设置两个部分:

  • 规则信息:包括规则名称、规则分类、规则标识以及是否启用的设置。
  • 规则设置:是否启用左边部分是事实数据,右边部分是动作数据,每一行是一条规则。

生成 DRL 规则文件的代码

以下代码演示了如何根据业务需求动态生成 DRL 规则文件。代码通过读取 JSON 格式的规则定义,过滤和转换数据,然后使用 Drools 提供的 ObjectDataCompiler 来生成 DRL 文件。

代码详解
java 复制代码
import java.io.ByteArrayInputStream;
import java.io.InputStream;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import com.fasterxml.jackson.core.type.TypeReference;
import org.drools.template.ObjectDataCompiler;

/**
 * DroolsRuleUtil 类用于根据业务需求动态生成 DRL 规则文件。
 */
public class DroolsRuleUtil {

    /**
     * 生成 DRL 规则文件。
     *
     * @param saveReSetPVO 保存规则设置的对象
     * @return 生成的 DRL 规则字符串
     */
    public static String generateDroolsDrl(SaveReSetPVO saveReSetPVO) {
        // 检查规则启用标志、规则定义详情和 DRT 模板是否有效
        if (Objects.equals(saveReSetPVO.getEnableFlag(), ConstantsRe.YES)
                && StringUtils.isNotBlank(saveReSetPVO.getDefineDetail())
                && StringUtils.isNotBlank(saveReSetPVO.getDrtRuleTemplate())) {

            // 将 JSON 格式的规则定义转换为 List<Map<String, Object>>
            List<Map<String, Object>> dataList = JacksonUtil.json2bean(saveReSetPVO.getDefineDetail(),
                    new TypeReference<List<Map<String, Object>>>() {});
            
            // 过滤出启用的规则
            dataList = dataList.stream()
                    .filter(e -> Objects.equals(ConvertUtil.createInteger(e.get("enable_flag")), ConstantsRe.YES))
                    .collect(Collectors.toList());

            if (CollectionUtils.isNotEmpty(dataList)) {
                // 将空值转换为 "null"
                for (Map<String, Object> map : dataList) {
                    for (Map.Entry<String, Object> entry : map.entrySet()) {
                        if (StringUtils.isBlank(ConvertUtil.createString(entry.getValue()))) {
                            map.replace(entry.getKey(), "null");
                        }
                    }
                }
                
                // 将 DRT 模板字符串转换为输入流
                InputStream inputStream = new ByteArrayInputStream(saveReSetPVO.getDrtRuleTemplate().getBytes());
                
                // 使用 ObjectDataCompiler 根据模板和数据生成 DRL 规则文件
                return new ObjectDataCompiler().compile(dataList, inputStream);
            } else {
                // 如果数据列表为空,返回 null
                return null;
            }
        }
        // 如果启用标志、规则定义详情或 DRT 模板无效,返回 null
        return null;
    }
}

代码解析

  1. 检查规则启用标志和内容有效性

    • 首先,检查 saveReSetPVO 对象的 enableFlag 是否为启用状态,并确保 defineDetaildrtRuleTemplate 不为空。
  2. 转换和过滤规则定义数据

    • 使用 JacksonUtil.json2bean 将 JSON 格式的规则定义转换为 List<Map<String, Object>>
    • 通过 streamfilter 方法,过滤出 enable_flag 为启用状态的规则。
  3. 处理空值

    • 遍历规则列表,将所有空值转换为字符串 "null",以避免生成规则时出现空值错误。
  4. 生成 DRL 规则文件

    • 将 DRT 模板字符串转换为输入流,使用 Drools 提供的 ObjectDataCompiler 根据模板和数据生成 DRL 规则文件。

业务规则配置示例

根据图示的规则编辑界面,以下是生成的 DRL 规则文件示例:

java 复制代码
package org.drools
import com.xinyuan.re.utils.DateUtils
declare SuppliersNumberFactPVO
	purchaseMethod: String
	projectStage: String
	suppliersNumber: Integer
end
declare SubmitTaskVerifyMessage
	state: int
	text: String
end

rule "re_openbid_supplier_count_0"
	when 
		$suppliers_number_fact_p_v_o : SuppliersNumberFactPVO(("00380002,00380024,00380020,00380003" == "null"  ||  purchaseMethod memberOf "00380002,00380024,00380020,00380003") && ("1" == "null"  ||  projectStage == 1	) && ("3" == "null"  ||  suppliersNumber < 3));
		$submit_task_verify_message : SubmitTaskVerifyMessage();
	then 
		$submit_task_verify_message.setState(2);
		$submit_task_verify_message.setText("招标的项目,投标人数量少于3个不得开标");
end

rule "re_openbid_supplier_count_1"
	when 
		$suppliers_number_fact_p_v_o : SuppliersNumberFactPVO(("00380002,00380003,00380020,00380024" == "null"  ||  purchaseMethod memberOf "00380002,00380003,00380020,00380024") && ("2" == "null"  ||  projectStage == 2	) && ("3" == "null"  ||  suppliersNumber < 3));
		$submit_task_verify_message : SubmitTaskVerifyMessage();
	then 
		$submit_task_verify_message.setState(2);
		$submit_task_verify_message.setText("资审阶段的项目,申请人数量少于3个不得开启");
end

结论

通过以上代码和示例,我们可以根据业务需求动态生成 DRL 规则文件。动态生成的 DRL 文件可以根据不同的业务场景进行定制化,提升了业务规则配置的灵活性和效率。

接下来可以学习,(三)基于业务数据动态调用 DRL 规则文件:详细实现与测试指南,形成规则引擎闭环。

相关推荐
paopaokaka_luck1 小时前
基于SpringBoot+Uniapp的健身饮食小程序(协同过滤算法、地图组件)
前端·javascript·vue.js·spring boot·后端·小程序·uni-app
Villiam_AY1 小时前
Redis 缓存机制详解:原理、问题与最佳实践
开发语言·redis·后端
飛_2 小时前
解决VSCode无法加载Json架构问题
java·服务器·前端
木棉软糖4 小时前
一个MySQL的数据表最多能够存多少的数据?
java
魔尔助理顾问4 小时前
系统整理Python的循环语句和常用方法
开发语言·后端·python
程序视点5 小时前
Java BigDecimal详解:小数精确计算、使用方法与常见问题解决方案
java·后端
愿你天黑有灯下雨有伞5 小时前
Spring Boot SSE实战:SseEmitter实现多客户端事件广播与心跳保活
java·spring boot·spring
你的人类朋友5 小时前
❤️‍🔥微服务的拆分策略
后端·微服务·架构
Java初学者小白5 小时前
秋招Day20 - 微服务
java
狐小粟同学6 小时前
JavaEE--3.多线程
java·开发语言·java-ee