【Drools】(一)基于业务需求动态生成 DRT 规则模板:事实与动作定义详解

(一)基于业务需求动态生成 DRT 规则模板:事实与动作定义详解

背景

在业务规则管理中,DRT 文件(Drools Rule Template)用于定义和重用规则模板,这些模板可以动态地根据实际业务需求进行填充和生成。通过动态生成 DRT 文件,我们可以根据不同的业务场景创建定制化的规则,从而提高业务规则配置的灵活性和效率。本文将介绍如何根据事实和动作定义动态生成 DRT 规则模板文件,并提供详细的代码注释,以帮助理解其生成过程。
接下来,我将进一步完善以下两个部分,以形成完整的规则引擎闭环:
(二) 基于DRT 规则模板动态配置,生成DRL规则文件
(三) 基于业务需求动态调用DRL规则文件

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

在这里插入图片描述

在这里插入图片描述

DRT 文件介绍

在这里插入图片描述

DRT 文件格式主要用于定义可重用的规则模板。一个标准的 DRT 文件通常包括以下部分:

  1. 模板头部:定义规则模板的基本信息。
  2. 包声明:指定规则模板所在的包。
  3. 导入语句:导入规则模板中需要使用的类或库。
  4. 事实声明:定义规则模板中涉及的事实类型及其属性。
  5. 动作声明:定义规则模板中触发的动作及其方法。
  6. 规则定义:具体的规则内容,包括 whenthen 部分。
  7. 模板结束标识:标记规则模板的结束。

示例 DRT 文件

以下是一个 DRT 文件的示例,展示了其基本结构和实际应用:

/*** 规则模板头部*/
template "exampleRuleTemplate"/*** 包声明*/
package com.example.rules/*** 导入语句*/
import com.example.models.Person;
import com.example.utils.DateUtils;/*** 事实声明*/
declare Personname: Stringage: intbirthDate: java.util.Date
end/*** 动作声明*/
declare ActionsetName(name: String);setAge(age: int);setBirthDate(birthDate: java.util.Date);
end/*** 规则定义*/
rule "exampleRule"when$person: Person(age > 18, birthDate >= DateUtils.getStartOfYear())thenAction action = new Action();action.setName($person.getName());action.setAge($person.getAge());action.setBirthDate($person.getBirthDate());// 其他业务逻辑
end

说明

  • 模板头部

    • template "exampleRuleTemplate": 这是规则模板的标识符,用于引用和填充模板内容。
  • 包声明

    • package com.example.rules: 指定规则模板所在的包,以便在项目中组织和管理规则模板。
  • 导入语句

    • import com.example.models.Person;: 导入用于事实声明的 Person 类。
    • import com.example.utils.DateUtils;: 导入用于日期处理的工具类 DateUtils
  • 事实声明

    • declare Person: 声明事实类型 Person,包括其属性 nameagebirthDate
    • end: 结束事实声明部分。
  • 动作声明

    • declare Action: 声明动作类型 Action,包括其方法 setNamesetAgesetBirthDate
    • end: 结束动作声明部分。
  • 规则定义

    • rule "exampleRule": 定义规则 exampleRule,包括规则名称和描述。
    • when: 规则的条件部分,用于匹配满足特定条件的事实。
      • $person: Person(age > 18, birthDate >= DateUtils.getStartOfYear()): 匹配年龄大于 18 岁且出生日期在当前年份开始之后的 Person 对象。
    • then: 规则的动作部分,用于触发匹配规则后的操作。
      • 创建 Action 对象并设置其属性。
      • 执行其他业务逻辑。

动态生成 DRT 文件

DrtTemplateUtil

DrtTemplateUtil 类提供了动态生成 DRT 规则模板文件的方法。以下是该类的详细实现和功能说明:

/*** DrtTemplateUtil - 动态生成 DRT 规则模板的工具类*/
public class DrtTemplateUtil {/*** 生成 DRT 规则模板** @param factDefine 事实定义对象,包含事实类型及其属性* @param actionDefine 动作定义对象,包含动作类型及其方法* @param ruleCode 规则代码,用于标识生成的规则模板* @return 生成的 DRT 规则模板字符串*/public static String generateDrtTemplate(GetReFactDefineRVO factDefine, GetReActionDefineRVO actionDefine, String ruleCode) {StringBuilder sb = new StringBuilder();// 添加模板头部sb.append(Constants_public.ORG_DRT_TEMPLATE_HEADER).append("\n");// 添加事实和动作定义列sb.append(getCustomParams(factDefine.getClass_params()));sb.append(getCustomParams(actionDefine.getClass_params()));sb.append("\n");// 添加包声明sb.append(Constants_public.ORG_DRT_PACKAGE).append(" ").append(Constants_public.ORG_DRT_PACKAGE_NAME).append("\n");sb.append("\n");// 添加导入语句getImport(sb);// 添加事实和动作声明getDeclare(factDefine, sb);getDeclare(actionDefine, sb);sb.append("\n");// 添加规则定义sb.append(Constants_public.ORG_DRT_TEMPLATE).append(" ").append("\"").append(ruleCode).append("\"").append("\n");getRule(factDefine, actionDefine, ruleCode, sb);// 添加模板结束标识sb.append(Constants_public.ORG_DRT_END_TEMPLATE);return sb.toString();}/*** 生成规则定义部分** @param factDefine 事实定义对象* @param actionDefine 动作定义对象* @param ruleCode 规则代码* @param sb StringBuilder 对象,用于构建规则模板字符串*/private static void getRule(GetReFactDefineRVO factDefine, GetReActionDefineRVO actionDefine, String ruleCode, StringBuilder sb) {// 添加规则标识sb.append(Constants_public.ORG_DRT_RULE).append(" \"").append(ruleCode).append(Constants_public.ORG_DRT_ROW_NUMBER).append("\"\n").append(DroolsUtil.tabNum(1)).append(Constants_public.ORG_DRT_WHEN).append(" \n");// 添加事实定义sb.append(DroolsUtil.tabNum(2)).append("$").append(DroolsUtil.getClassAlias(factDefine.getClass_name())).append(" : ").append(factDefine.getClass_name()).append("(").append(getConditions(factDefine)).append(")").append(";\n");// 添加日期处理逻辑List<ConditionDefineRVO> dateConditions = factDefine.getConditionDefineRVOList().stream().filter(e -> StringUtils.isNotBlank(e.getExpression()) && e.getExpression().contains(Constants_public.ORG_DRT_TEMPLATE_DATA_SIGN)).collect(Collectors.toList());List<String> verifyDates = getVerifyDates(factDefine, dateConditions, sb);// 添加动作定义sb.append(DroolsUtil.tabNum(2)).append("$").append(DroolsUtil.getClassAlias(actionDefine.getClass_name())).append(" : ").append(actionDefine.getClass_name()).append("()").append(";\n").append(DroolsUtil.tabNum(1)).append(Constants_public.ORG_DRT_THEN).append(" \n").append(getActions(actionDefine, dateConditions, verifyDates)).append("\n").append(Constants_public.ORG_DRT_END).append("\n");}/*** 获取条件表达式** @param factDefine 事实定义对象* @return 条件表达式字符串*/private static String getConditions(GetReFactDefineRVO factDefine) {return factDefine.getConditionDefineRVOList().stream().filter(e -> StringUtils.isNotBlank(e.getExpression()) && !e.getExpression().contains(Constants_public.ORG_DRT_TEMPLATE_DATA_SIGN)).map(e -> e.getExpression().contains("@{") ? "(" + getNullStrOfRegex(e.getExpression()) + e.getExpression() + ")" : e.getExpression()).collect(Collectors.joining(Constants_public.ORG_DRT_DEFAULT_RELATION));}/*** 获取日期验证列表** @param factDefine 事实定义对象* @param dateConditions 日期条件列表* @param sb StringBuilder 对象* @return 日期验证列表*/private static List<String> getVerifyDates(GetReFactDefineRVO factDefine, List<ConditionDefineRVO> dateConditions, StringBuilder sb) {List<String> verifyDates = new ArrayList<>();for (int i = 0; i < dateConditions.size(); i++) {StringBuilder dateCondition = new StringBuilder();dateCondition.append("$").append(DroolsUtil.getClassAlias(factDefine.getClass_name())).append(".get").append(StringUtils.capitalize(Constants_public.ORG_DRT_TEMPLATE_START_DATE)).append("(), ").append("$").append(DroolsUtil.getClassAlias(factDefine.getClass_name())).append(".get").append(StringUtils.capitalize(Constants_public.ORG_DRT_TEMPLATE_END_DATE)).append("()");String expression = dateConditions.get(i).getExpression();sb.append(DroolsUtil.tabNum(2)).append("$verifyDate").append(i).append(" : ").append(MessageFormat.format(Constants_public.ORG_DRT_TEMPLATE_WHEN_DATE_CALL, getNullStrOfRegex(expression), dateCondition)).append(expression.substring(expression.indexOf(")") + 1)).append("\n");verifyDates.add("$verifyDate" + i);}return verifyDates;}/*** 获取动作表达式** @param actionDefine 动作定义对象* @param dateConditions 日期条件列表* @param verifyDates 日期验证列表* @return 动作表达式字符串*/private static String getActions(GetReActionDefineRVO actionDefine, List<ConditionDefineRVO> dateConditions, List<String> verifyDates) {StringBuilder sb = new StringBuilder();String[] actionParams = getCustomParams(actionDefine.getClass_params()).split("\n");for (String action : actionParams) {sb.append(DroolsUtil.tabNum(dateConditions.isEmpty() ? 2 : 3)).append("$").append(DroolsUtil.getClassAlias(actionDefine.getClass_name())).append(".set").append(StringUtils.capitalize(action)).append("(@{").append(action).append("});").append("\n");}if (!dateConditions.isEmpty()) {sb.insert(0, DroolsUtil.tabNum(2) + MessageFormat.format("if ({0}) '{", String.join(Constants_public.ORG_DRT_DEFAULT_RELATION, verifyDates)) + "\n");sb.append(DroolsUtil.tabNum(2)).append("}");}return sb.toString();}/*** 生成正则表达式匹配的空字符串,用于数据校验** @param expression 原始表达式* @return 生成的空字符串*/private static String getNullStrOfRegex(String expression) {Pattern pattern = Pattern.compile(Constants_public.GLOBAL_PARAMS_PATTERN);Matcher matcher = pattern.matcher(expression);StringBuilder nullStr = new StringBuilder();while (matcher.find()) {nullStr.append("\"").append(matcher.group()).append("\" == \"null\" ").append(Constants_public.ORG_DRT_OR_RELATION).append(" ");}return nullStr.toString();}/*** 添加导入语句到 StringBuilder 对象中** @param sb StringBuilder 对象*/private static void getImport(StringBuilder sb) {sb.append(Constants_public.ORG_DRT_IMPORT).append(" com.xinyuan.re.utils.DateUtils").append("\n\n");}/*** 添加声明部分到 StringBuilder 对象中** @param classParamsAndName 事实或动作定义对象* @param sb StringBuilder 对象*/private static void getDeclare(GetClassParamsAndNameRVO classParamsAndName, StringBuilder sb) {sb.append(Constants_public.ORG_DRT_DECLARE).append(" ").append(classParamsAndName.getClass_name()).append("\n").append(classParamsAndName.getClass_params()).append(Constants_public.ORG_DRT_END).append("\n");}/*** 格式化自定义参数,去除多余的空格和制表符** @param classParams 自定义参数字符串* @return 格式化后的参数字符串*/public static String getCustomParams(String classParams) {return classParams.replaceAll(":\\s\\w+\\n", "\n").replaceAll("\\t", "");}
}

方法功能

  • generateDrtTemplate:生成 DRT 文件模板的核心方法,接受事实定义、动作定义和规则代码作为输入,返回格式化的 DRT 文件模板字符串。
  • getRule:构建规则的 whenthen 部分,处理事实条件、动作执行及日期验证。
  • getNullStrOfRegex:生成正则表达式匹配的空字符串,用于数据校验。
  • getImport:添加必要的导入语句到 StringBuilder 对象中。
  • getDeclare:添加类声明部分到 StringBuilder 对象中,包括类名和参数定义。
  • getCustomParams:格式化自定义参数,去除多余的空格和制表符。

示例

以下是如何使用 DrtTemplateUtil 类生成 DRT 文件模板的示例:

GetReFactDefineRVO factDefine = new GetReFactDefineRVO();
// 设置 factDefine 的属性
// ...GetReActionDefineRVO actionDefine = new GetReActionDefineRVO();
// 设置 actionDefine 的属性
// ...String ruleCode = "exampleRuleCode";// 生成 DRT 文件模板
String drtTemplate = DrtTemplateUtil.generateDrtTemplate(factDefine, actionDefine, ruleCode);// 输出模板
System.out.println(drtTemplate);

结论

通过使用 DrtTemplateUtil 类,我们能够根据不同的业务需求动态生成符合规范的 DRT 文件模板。这种方法不仅提高了规则配置的灵活性,还简化了规则模板的生成过程,使得规则管理更加高效。希望本文的示例和详细注释能帮助您理解 DRT 文件的结构及其生成方法。


如果有进一步的问题或需要更多帮助,请随时告诉我!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/web/50311.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Android 10.0 Launcher 启动流程

在前面SystemUI启动流程中说到&#xff0c;在SystemServer中会去启动各种系统服务&#xff0c;这里的launcher也是启动的其中一个服务ActivityManagerService去启动的。在android10之前&#xff0c;系统四大组件的启动都是在ActivityManagerService中&#xff0c;在android10中…

前端创建仓库的详细步骤

第一步点击号新建仓库 第二步输入完仓库名称路径会自己出来然后点击创建 第三步在自己创建的文件夹右键点击GIt Bash Here 第四步把我框的这些一个一个的输在Git Bash Here中每输入一个回车一个 第五步全部输入完以后CtrlF5自动刷新下就好了 然后文件夹就会有.git了

机器视觉12-相机

相机 作用: 工业相机 是 机器视觉系统 的重要组成部分 最本质的功能就是通过CCD或CMOS成 像传感器将镜头产生的光信号转变为 有序的电信号&#xff0c;并将这些信息通过相 应接口传送到计算机主机 工业相机分类 目前业内没有对相机进行明确的分类定义&#xff0c; 以下分类是…

Python 学习中的 API,如何调用API ?

1.1 API的定义 API&#xff0c;全称是Application Programming Interface&#xff08;应用程序编程接口&#xff09;。它是一组定义好的协议和工具&#xff0c;用于在软件应用程序之间进行通信。API可以简化软件开发&#xff0c;使不同的应用程序能够相互协作。它是软件开发中…

数字车间与智能工厂:区别、联系与制造业的未来转型

数字车间和智能工厂在制造业中扮演着重要角色&#xff0c;它们之间存在明显的区别和紧密的联系。以下是对两者区别和联系的详细阐述&#xff1a; 一、区别 定义与范围 数字车间&#xff1a;数字车间是指通过信息化技术、智能化装备和数据化管理等手段&#xff0c;实现生产过程全…

【Python系列】Python 程序的优雅退出:使用`sys.exit()`控制程序终止

&#x1f49d;&#x1f49d;&#x1f49d;欢迎来到我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您的想法和见解。 推荐:kwan 的首页,持续学…

笔记本电脑怎么录屏?5个小技巧(2024最全)

在今天&#xff0c;录屏功能已经不再是专业人士的专属&#xff0c;而是融入了普通人的日常生活与工作之中。想要记录游戏的精彩瞬间、分享软件的操作教程&#xff0c;或是保存屏幕上的重要信息&#xff0c;录屏都能帮你一键搞定。那么&#xff0c;对于我们这些日常使用笔记本电…

初始K8s

K8S 基本概念: K8S 的全称为 Kubernetes (K12345678S)&#xff0c;PS&#xff1a;“嘛&#xff0c;写全称也太累了吧&#xff0c;不如整个缩写”。 作用&#xff1a; 用于自动部署、扩展和管理“容器化&#xff08;containerized&#xff09;应用程序”的开源系统。 可以理解成…

火狐浏览器怎么切换ip:详细步骤与注意事项

随着互联网的飞速发展&#xff0c;网络环境的复杂性和安全性问题日益凸显。对于需要保护个人隐私、突破地域限制或进行网络测试的用户来说&#xff0c;切换IP地址成为了一项重要的技能。火狐浏览器&#xff0c;作为一款备受欢迎的开源浏览器&#xff0c;凭借其强大的自定义功能…

【计算机网络】TCP和UDP的封装以及案例

TCP和UDP的封装以及案例 背景知识TCP实现UDP实现封装Network用NetWork再次实现TCP和UDP小知识点 背景知识 TCP&#xff1a;传输控制协议&#xff08;Transmission Control Protocol&#xff09; UDP&#xff1a;用户数据报协议 &#xff08;User Datagram Protocol&#xff09…

AI的欺骗游戏:揭示多模态大型语言模型的易受骗性

人工智能咨询培训老师叶梓 转载标明出处 多模态大型语言模型&#xff08;MLLMs&#xff09;在处理包含欺骗性信息的提示时容易生成幻觉式响应。尤其是在生成长响应时&#xff0c;仍然是一个未被充分研究的问题。来自 Apple 公司的研究团队提出了MAD-Bench&#xff0c;一个包含8…

网站打不开怎么办,收藏以备不时之需

DNS设置示范教程 部分地区有使用移动网络的小伙伴们吐槽无法访问部分网站的情况&#xff0c;同样的网站&#xff0c;使用电信和联通的用户就能正常访问。 这其实有很大几率是由于运营商的网络问题导致的&#xff0c;容易出现网站打不开的结果。 要解决移动网络无法访问的情况…

(面试必看!)一些和多线程相关的面试考点

文章导读 引言考点1. CAS 指令&#xff08;重点&#xff09;一、什么是CAS二、CAS 的优点三、CAS 的缺点四、ABA问题五、相关面试题 考点2. 信号量&#xff08;semaphore&#xff09;一、基本概念二、信号量的主要操作三、信号量的应用四、相关面试题 考点3、CountDownLatch 类…

DHCP笔记

DHCP---动态主机配置协议 作用&#xff1a;为终端动态提供IP地址&#xff0c;子网掩码&#xff0c;网关&#xff0c;DNS网址等信息 具体流程 报文抓包 在DHCP服务器分配iP地址之间会进行广播发送arp报文&#xff0c;接收IP地址的设备也会发送&#xff0c;防止其他设备已经使用…

卓码软件测评:软件功能测试和非功能测试详情介绍

随着信息技术的不断发展&#xff0c;软件在我们日常生活与工作中扮演着越来越重要的角色。然而&#xff0c;软件质量的好坏直接关系到使用者的体验和企业的声誉。在软件开发过程中&#xff0c;功能测试和非功能测试作为保证软件质量的重要手段&#xff0c;受到了越来越多的关注…

古文:文天祥《正气歌》

原文 正气歌 【作者】文天祥 【朝代】宋 余囚北庭&#xff0c;坐一土室。室广八尺&#xff0c;深可四寻。单扉低小&#xff0c;白间短窄&#xff0c;污下而幽暗。当此夏日&#xff0c;诸气萃然&#xff1a;雨潦四集&#xff0c;浮动床几&#xff0c;时则为水气&#xff1b;涂泥…

YAML 语法规范

文章目录 YAML 语法规范一、简介二、基本语法三、高级语法四、示例解析五、注意事项YAML 语法规范 一、简介 YAML(YAML Ain’t Markup Language)是一种专门用来写配置文件的语言,具有简洁、易读、易解析等特点。YAML的设计理念是为人类和机器之间的沟通提供一种更加直观、…

Chiplet SPI User Guide 详细解读

目录 一. 基本介绍 1.1.整体结构 1.2. 结构细节与功能描述 二. 输入输出接口 2.1. IO Ports for SPI Leader 2.2. IO Ports for SPI Follower 2.3. SPI Mode Configuration 2.4. Leader IP和Follower IP功能图 三. SPI Programming 3.1. Leader Register Descripti…

基于FPGA的数字信号处理(19)--行波进位加法器

1、10进制加法是如何实现的&#xff1f; 10进制加法是大家在小学就学过的内容&#xff0c;不过在这里我还是帮大家回忆一下。考虑2个2位数的10进制加法&#xff0c;例如&#xff1a;15 28 43&#xff0c;它的运算过程如下&#xff1a; 个位两数相加&#xff0c;结果为5 8 1…

苹果 iCloud 钥匙串是什么?如何查看及对其进行设置?

在当今的数字世界中安全性和便利性是人们关注的两大重点。无论是社交媒体账户、还是网购平台等&#xff0c;几乎每个在线服务都需要登录账户。如何安全地管理和存储这些账户密码成为了用户们的一大挑战。 iCloud 钥匙串 我们先来看一看什么是 iCloud 钥匙串&#xff0c;iClou…