news 2026/9/18 17:17:29

Camunda DMN 决策引擎实战:独立运行与 BPMN 业务规则任务集成指南

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Camunda DMN 决策引擎实战:独立运行与 BPMN 业务规则任务集成指南

Camunda DMN 决策引擎实战:独立运行与 BPMN 业务规则任务集成指南

【免费下载链接】camunda-bpm-platformCamunda 7 CE is End of Life (EoL). Please check out Camunda 8 instead (https://github.com/camunda/camunda) or read about Camunda 7 Enterprise End of Life (https://camunda.com/blog/2025/02/camunda-7-enterprise-end-of-life-extension/) – Camunda 7 CE was a flexible framework for workflow and decision automation using BPMN and DMN.项目地址: https://gitcode.com/GitHub_Trending/ca/camunda-bpm-platform

camunda-engine-dmn是 Camunda 7 平台中基于 Java 编写的轻量级 DMN(Decision Model and Notation)决策执行引擎,能够解析 DMN 决策模型并求值决策。本文将围绕 engine-dmn/README.md 的核心内容展开:先讲解如何以独立(Standalone)方式把引擎引入 Maven 工程并用纯 Java API 解析、求值决策;再演示如何让 BPMN 流程中的业务规则任务(Business Rule Task)通过camunda:decisionRef无缝引用 DMN 决策,将决策逻辑编排进工作流。读完本文,你将掌握 DMN 引擎的最小可运行工程搭建、决策表求值结果 API、底层求值与命中策略实现,以及它与 Camunda 流程引擎的完整集成链路。

一、模块定位:可独立运行、也可与 BPMN/CMMN 组合使用

根据 engine-dmn/README.md 的定位说明,该决策引擎以 Java 实现,核心价值在于"轻量"(Lightweight Execution Engine for DMN),并且既可以与 BPMN、CMMN 无缝组合使用,也可以完全独立运行

从仓库结构看,engine-dmn模块是一个由多个子模块组成的多模块工程:

  • engine-dmn/engine:引擎主体,提供DmnEngine接口、默认实现与全部内部机制;
  • engine-dmn/feel-api:FEEL 表达式的 SPI 接口(FeelEngineFeelEngineFactory);
  • engine-dmn/feel-juel:将 FEEL 语法翻译为 JUEL 求值的兼容实现;
  • engine-dmn/feel-scala:对 Scala FEEL Engine 的集成实现(参见 feel-scala/README.md),是现代版本默认使用的 FEEL 引擎。

从 engine-dmn/engine/pom.xml 的依赖声明可以印证引擎的组成:它依赖camunda-dmn-model(DMN 模型 API)、camunda-engine-feel-apicamunda-engine-feel-juelcamunda-engine-feel-scalafeel-engine(scala-shaded)以及camunda-juel(表达式语言求值)、camunda-commons-typed-values(类型化变量)与camunda-commons-utils。这意味着一个引擎实例内部实际串联起了 DMN 模型解析、表达式求值与类型化变量三大能力。

二、独立使用:三分钟跑通一个 DMN 引擎

2.1 引入 Maven 坐标

独立使用方式下,只需在项目中加入如下依赖(原文档示例,groupId 为org.camunda.bpm.dmn):

<dependency> <groupId>org.camunda.bpm.dmn</groupId> <artifactId>camunda-engine-dmn</artifactId> <version>${version.camunda}</version> </dependency>

${version.camunda}需要替换为具体的版本号。需要说明的是,当前仓库的engine-dmn/engine/pom.xml中版本为7.24.0-SNAPSHOT,且注明7.24.0 是 Camunda 7 社区版在 Maven Central 发布的最后一个版本,后续该构件不会再发布新版本(企业版提供扩展维护),使用时应留意这一版本前提。

2.2 编写第一个求值程序

原文档给出了一个完整的独立使用示例,核心步骤分为"构建引擎 → 解析决策 → 准备输入数据 → 求值决策表"四步:

public class DmnApp { public static void main(String[] args) { // configure and build the DMN engine DmnEngine dmnEngine = DmnEngineConfiguration.createDefaultDmnEngineConfiguration().buildEngine(); // parse a decision DmnDecision decision = dmnEngine.parseDecision("orderDecision", "CheckOrder.dmn"); Map<String, Object> data = new HashMap<String, Object>(); data.put("status", "gold"); data.put("sum", 354.12d); // evaluate a decision DmnDecisionTableResult result = dmnEngine.evaluateDecisionTable(decision, data); } }

各步骤的关键点如下:

  1. 构建引擎DmnEngineConfiguration.createDefaultDmnEngineConfiguration().buildEngine()。从源码看,DmnEngineConfiguration.java 是抽象类,createDefaultDmnEngineConfiguration()返回默认实现DefaultDmnEngineConfigurationbuildEngine()在 DefaultDmnEngineConfiguration.java 中会先调用init()(依次初始化指标收集器、决策表求值监听器、决策求值监听器、脚本引擎解析器、表达式语言默认值、EL Provider 与 FEEL 引擎),随后返回new DefaultDmnEngine(this)

  2. 解析决策parseDecision("orderDecision", "CheckOrder.dmn")。其中orderDecision是 DMN 文件中<dmn:decision>元素的id属性(即决策 key),第二个参数可以是InputStreamDmnModelInstance。DmnEngine.java 中定义了完整的 API 面,除parseDecision外还提供:

    • parseDecisions(...):解析文件中的全部决策;
    • parseDecisionRequirementsGraph(...):解析决策需求图(DRG);
    • evaluateDecisionTable(...):以决策表结果形式求值;
    • evaluateDecision(...):求值任意支持的决策逻辑(决策表、字面量表达式等),返回更通用的DmnDecisionResult。 若给定的 key 找不到对应决策,DefaultDmnEngine.java 会抛出unableToFindDecisionWithKey异常。
  3. 准备输入数据:普通Map<String, Object>即可,引擎内部会通过Variables.fromMap(variables).asVariableContext()将其转换为类型化的VariableContext,供表达式求值使用。

  4. 求值决策表evaluateDecisionTable返回DmnDecisionTableResult。注意该方法要求目标决策必须实现为决策表(decision table),否则抛出decisionIsNotADecisionTable异常。

2.3 读取求值结果:DmnDecisionTableResult API

evaluateDecisionTable的返回值是DmnDecisionTableResult(本质是List<DmnDecisionRuleResult>)。DmnDecisionTableResult.java 定义了以下便捷方法:

方法语义
getFirstResult()返回第一条命中的决策规则结果,无命中则返回 null
getSingleResult()返回唯一命中结果,若命中多于一条则抛出DmnEngineException
collectEntries(outputName)按输出名收集所有命中规则在该输出列上的值
getResultList()返回所有命中规则的输出名→值映射列表
getSingleEntry()断言"仅一条命中且仅一个输出",返回该输出值
getSingleEntryTyped()getSingleEntry(),但返回类型化值TypedValue

在"唯一命中 + 单输出"的典型场景(例如 UNIQUE 命中策略的审批人决策)中,一行result.getSingleEntry()即可取回最终决策值。

三、决策表求值原理:输入列逐列过滤、命中策略收敛

为了让"求值"不只是黑盒调用,这里结合源码补充其底层实现。DecisionTableEvaluationHandler.java 是决策表求值的核心处理器,其evaluate流程为:

  1. 逐输入列求值:对每个输入列,先求值输入表达式(Input Expression),得到类型化输入值(TypedValue),并把当前输入值注入局部VariableContext(可通过输入列的inputVariable在规则条件中引用);
  2. 逐列过滤规则:从全部规则开始,用每一列的输入项(Input Entry,即条件表达式)对候选规则做过滤,只有条件求值为true的规则进入下一轮,最终得到全部匹配规则(Matching Rules);
  3. 求值输出:对匹配规则逐列求值输出项(Output Entry),并将原始值按输出列的类型定义(Type Definition)转换为类型化值(可参考type包下的StringDataTypeTransformerIntegerDataTypeTransformerBooleanDataTypeTransformerDateDataTypeTransformerDoubleDataTypeTransformerLongDataTypeTransformer等内置类型转换器);
  4. 应用命中策略:调用决策表配置的HitPolicyHandler收敛匹配规则(见下文);
  5. 通知监听器:向所有注册的决策表求值监听器广播DmnDecisionTableEvaluationEvent

其中输入项(条件)若为 FEEL 表达式,会走evaluateFeelSimpleUnaryTests,即用 FEEL 引擎的evaluateSimpleUnaryTests求值简单一元测试(simple unary tests);空白输入项恒视为true

3.1 命中策略(Hit Policy)全景

命中策略决定多条规则命中时如何处理输出。DefaultHitPolicyHandlerRegistry.java 中的默认注册表完整覆盖了 DMN 规范定义的策略:

Hit Policy聚合器行为
UNIQUE恰好命中一条规则,否则异常
FIRST返回命中顺序中第一条规则输出
ANY多条命中时要求所有输出一致,否则抛DmnHitPolicyException
RULE ORDER返回所有命中规则的输出(保持规则顺序)
COLLECT返回所有命中规则的输出
COLLECTCOUNT返回命中规则数量
COLLECTSUM返回命中规则输出的总和
COLLECTMIN返回命中规则输出的最小值
COLLECTMAX返回命中规则输出的最大值

以 ANY 为例,AnyHitPolicyHandler.java 在apply中会比较所有匹配规则的输出映射:若全部相等则只保留第一条并返回;若存在不等则抛出anyHitPolicyRequiresThatAllOutputsAreEqual异常。该注册表支持通过addHandler扩展自定义命中策略处理器(SPI 位于impl.spi.hitpolicy)。

四、表达式语言与引擎配置

4.1 默认表达式语言

DMN 引擎支持 FEEL 与 JUEL 两类表达式。DefaultDmnEngineConfiguration.java 定义了四类表达式语言默认值:

  • defaultInputExpressionExpressionLanguage:输入表达式;
  • defaultInputEntryExpressionLanguage:输入项(条件);
  • defaultOutputEntryExpressionLanguage:输出项(结论);
  • defaultLiteralExpressionLanguage:字面量表达式。

在不开启 FEEL 遗留行为时,四者默认均为 FEEL;若设置enableFeelLegacyBehavior(true),则输入表达式与输出项回退为 JUEL,仅输入项保持 FEEL。注意表达式若在 DMN 文件中显式声明了expressionLanguage,将优先使用显式声明,配置值仅作用于未声明的表达式。

4.2 引擎默认依赖链

从 engine-dmn/engine/pom.xml 可以看到 FEEL 支持的完整依赖链:默认使用feel-enginescala-shaded)与camunda-engine-feel-scala;而camunda-engine-feel-juel则作为 FEEL 遗留行为的实现(对应 DefaultDmnEngineConfiguration.java 中enableFeelLegacyBehavior为 true 时使用FeelEngineFactoryImpl,否则使用ScalaFeelEngineFactory的逻辑)。camunda-juel为 JUEL 表达式提供底层 EL 求值能力。

4.3 常用可配置项

DmnEngineConfiguration(及默认实现DefaultDmnEngineConfiguration)还支持以下常用扩展点:

  • 指标收集器engineMetricCollector(...),默认实现为DefaultEngineMetricCollector,内部以AtomicLong统计累计执行的决策实例数(executed decision instances)与决策元素数(executed decision elements),并提供clearExecutedDecisionInstances()/clearExecutedDecisionElements()清零方法(见 DefaultEngineMetricCollector.java);
  • 求值监听器customPreDecisionTableEvaluationListeners(...)/customPostDecisionTableEvaluationListeners(...),以及决策级customPreDecisionEvaluationListeners(...)/customPostDecisionEvaluationListeners(...),可用于审计、日志或指标采集;
  • 脚本引擎解析器scriptEngineResolver(...),用于解析表达式语言对应的脚本引擎;
  • EL ProviderelProvider(...),默认JuelElProvider
  • FEEL 自定义函数feelCustomFunctionProviders(...),向 Scala FEEL 引擎注册自定义函数;
  • 转换器transformer(...),默认DefaultDmnTransformer,负责把 DMN 模型实例转换为引擎内部结构;
  • 空白输出处理setReturnBlankTableOutputAsNull(true)时,空白输出项也作为null写入结果(默认策略是丢弃空白输出项)。该选项有专门的测试类 ReturnBlankTableOutputAsNullTest.java 覆盖。

配置接口的完整方法清单参见 DmnEngineConfiguration.java,引擎的解析/求值 API 参见 DmnEngine.java。

五、在 BPMN 流程中实现业务规则任务

独立运行之外,更常见的生产场景是把 DMN 决策嵌入 BPMN 流程。原文档的第二部分给出了完整方案。

5.1 依赖与准备

在流程引擎应用中,需要引入流程引擎本体与内存数据库(示例中 H2 仅用于测试作用域):

<dependency> <groupId>org.camunda.bpm</groupId> <artifactId>camunda-engine</artifactId> <version>${version.camunda}</version> </dependency> <dependency> <groupId>com.h2database</groupId> <artifactId>h2</artifactId> <version>1.3.168</version> <scope>test</scope> </dependency>

5.2 在 BPMN 中引用 DMN 决策

在 BPMN 流程文件里声明一个业务规则任务(Business Rule Task),并通过 Camunda 扩展属性camunda:decisionRef指向 DMN 决策:

<bpmn:businessRuleTask id="assignApprover" camunda:decisionRef="invoice-assign-approver" camunda:resultVariable="approverGroups" name="Assign Approver Group(s)"> </bpmn:businessRuleTask>
  • camunda:decisionRef必填,值为 DMN 文件中决策的id(注意是id而非name),即invoice-assign-approver
  • camunda:resultVariable可选,指定将决策结果保存到流程变量名,示例中为approverGroups;不声明时结果默认写入流程变量decisionResult

对应的 DMN 文件片段:

<dmn:decision id="invoice-assign-approver" name="Assign Approver"> ... </dmn:decision>

从流程引擎的解析源码看,camunda:decisionRef的处理位于 BpmnParse.java:解析器读取CAMUNDA_BPMN_EXTENSIONS_NS命名空间下的decisionRef属性,并将其包装为参数值提供者(ParameterValueProvider),同时支持以下配套绑定属性:

  • camunda:decisionRefBinding:绑定方式(latest/deployment/version/versionTag);
  • camunda:decisionRefVersion:结合version绑定指定决策版本;
  • camunda:decisionRefVersionTag:结合versionTag绑定指定版本标签;
  • camunda:decisionRefTenantId:指定多租户场景下的租户。

5.3 部署并启动流程

最后,把 BPMN 文件与 DMN 文件作为一个 Deployment 一起部署,再按流程 key 启动流程实例:

public class App { public static void main(String[] args) { ProcessEngine processEngine = ProcessEngineConfiguration.createStandaloneInMemProcessEngineConfiguration() .buildProcessEngine(); try { processEngine.getRepositoryService() .createDeployment() .name("invoice deployment") .addClasspathResource("invoice.bpmn") .addClasspathResource("assign-approver-groups.dmn") .deploy(); processEngine.getRuntimeService() .startProcessInstanceByKey("invoice", createVariables() .putValue("invoceNumber", "2323")); } finally { processEngine.close(); } } }

要点说明:

  • createStandaloneInMemProcessEngineConfiguration()创建基于内存数据库的独立流程引擎,适合测试与演示;
  • addClasspathResource同时注册 BPMN 与 DMN 资源,流程引擎会在部署阶段解析 DMN 文件并建立decisionRef与决策 id 的映射;
  • startProcessInstanceByKey("invoice", ...)中的invoice是 BPMN 流程的id,启动后流程流转至业务规则任务时会自动执行对应的 DMN 决策,并把结果写入resultVariable指定的流程变量;
  • finally中的processEngine.close()用于释放引擎资源。

5.4 组合使用时的求值结果形态

需要留意的是,当 DMN 决策被流程引擎调用时,引擎内部同样走DmnEngine的求值链路(决策表求值 → 命中策略收敛 → 监听器通知),最终结果以DmnDecisionTableResult形式映射为流程变量。因此,第四节中关于命中策略与输出行为的说明,同样适用于 BPMN 集成场景。

六、版本说明与注意事项

  • 当前仓库engine-dmn/engine的版本为7.24.0-SNAPSHOT,根据 engine-dmn/engine/pom.xml 的说明,7.24.0 是 Camunda 7 社区版在 Maven Central 的最后一个发布版本,之后社区版不再发布新版本,如需要扩展维护请关注企业版方案;在实际项目中应把${version.camunda}替换为可用的正式版本号。
  • camunda:decisionRef引用的是 DMN 决策的id属性,拼写错误或文件中不存在该 id 时,求值/解析阶段会抛出异常(unableToFindDecisionWithKey)。
  • evaluateDecisionTable只适用于决策表类型的决策;若决策以字面量表达式(literal expression)等其他决策逻辑实现,应使用evaluateDecision通用求值 API(见 DmnEngine.java)。

七、延伸阅读

  • 引擎完整 API:DmnEngine.java
  • 配置与构建:DmnEngineConfiguration.java、DefaultDmnEngineConfiguration.java
  • 决策表求值实现:DecisionTableEvaluationHandler.java
  • 命中策略注册表:DefaultHitPolicyHandlerRegistry.java
  • 求值结果 API:DmnDecisionTableResult.java
  • 引擎功能测试示例:DmnEngineApiTest.java、EvaluateDecisionTest.java、HitPolicyTest.java
  • BPMNdecisionRef解析逻辑:BpmnParse.java

【免费下载链接】camunda-bpm-platformCamunda 7 CE is End of Life (EoL). Please check out Camunda 8 instead (https://github.com/camunda/camunda) or read about Camunda 7 Enterprise End of Life (https://camunda.com/blog/2025/02/camunda-7-enterprise-end-of-life-extension/) – Camunda 7 CE was a flexible framework for workflow and decision automation using BPMN and DMN.项目地址: https://gitcode.com/GitHub_Trending/ca/camunda-bpm-platform

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/18 17:16:05

PeopleSoft AWE工作流配置核心原理与实战指南

简介&#xff1a;本资源是一份面向PeopleSoft开发工程师与HCM系统实施人员的实战型工作流配置指南&#xff0c;聚焦Approval Workflow Engine&#xff08;AWE&#xff09;在费用报销场景中的端到端落地实践。文档以PT8.50FSCM9.1Oracle技术栈为基础&#xff0c;完整覆盖用户权限…

作者头像 李华
网站建设 2026/9/18 17:09:21

知识梳理转思维导图:用Python和Markmap自动生成教案PPTX

简介&#xff1a;面向小学四年级数学教学的学习课件&#xff0c;聚焦人教版四年级下册第五单元“三角形”的知识梳理与思维导图复习。课件包含系统的概念讲解与例题演练&#xff0c;覆盖三角形定义与稳定性、三边关系、按角/按边分类、内角和180以及多边形内角和公式等必考点&a…

作者头像 李华
网站建设 2026/9/18 17:08:44

从FGSM到CW:对抗样本生成与模型鲁棒性评估实践

简介&#xff1a;《基于深度学习的对抗样本生成技术研究综述》是一篇聚焦深度学习安全领域的学术综述&#xff0c;内容详实、结构清晰&#xff0c;适合人工智能、数据研究及网络安全方向的研究生和工程师阅读。文中从对抗样本的起源与基本原理入手&#xff0c;将生成方法划分为…

作者头像 李华
网站建设 2026/9/18 17:08:37

CANN社区组织管理全指南:SIG创建、成员变更与PMC/TSC治理实操

CANN社区组织管理全指南&#xff1a;SIG创建、成员变更与PMC/TSC治理实操 【免费下载链接】community 本项目是CANN开源社区的核心管理仓库&#xff0c;包含社区的治理章程、治理组织、通用操作指引及流程规范等基础信息 项目地址: https://gitcode.com/cann/community …

作者头像 李华