流程表达式
这篇解决什么
在网关、完成条件、选人规则里写 ${...},让 Flowable 用 UEL 算出布尔值或用户编号。读完能对上菜单里的表达式模板、candidateStrategy = 60,以及两个示例 Bean 为什么标了过时。
默认端口 48080,管理端前缀 /admin-api。PC 开发页 http://127.0.0.1:5800。模板在流程中心 → 流程设置 → 流程表达式。真正生效的是节点上那串表达式,不是模板行本身。
示意图:菜单只存可复用的字符串。运行时策略把字符串交给引擎求值。
从哪改
| 名称 | 说明 | 仓库路径 |
|---|---|---|
| 模板接口 | @RequestMapping("/bpm/process-expression") | ruoyi-office/yudao-module-bpm/.../controller/admin/definition/BpmProcessExpressionController.java |
| 模板表 | bpm_process_expression | .../dal/dataobject/definition/BpmProcessExpressionDO.java |
| 选人策略 | EXPRESSION = 60 | .../enums/BpmTaskCandidateStrategyEnum.java |
| 策略实现 | FlowableUtils.getExpressionValue | .../strategy/other/BpmTaskCandidateExpressionStrategy.java |
| 求值工具 | 任务上下文或变量 Map | .../util/FlowableUtils.java |
| 发起人示例 | ${bpmTaskAssignStartUserExpression.calculateUsers(execution)} | .../candidate/expression/BpmTaskAssignStartUserExpression.java |
| 上级示例 | calculateUsers(execution, level) | .../candidate/expression/BpmTaskAssignLeaderExpression.java |
| PC 列表 | 路由 /bpm/manager/process-expression | ruoyi-office-vben/apps/web-antd/src/views/bpm/processExpression/index.vue |
| 选择弹窗 | BPMN / SIMPLE 都能挑模板 | .../processExpression/components/select-modal.vue |
| 前端 API | /bpm/process-expression/** | .../src/api/bpm/processExpression/index.ts |
官方菜单:1186 流程设置,2731 流程表达式。按钮 bpm:process-expression:query / create / update / delete。字典 bpm_task_candidate_strategy 的 60 显示「流程表达式」。
模板不会自动执行
bpm_process_expression 没有监听器、没有定时扫描。设计器只是把 expression 字段填进节点。改模板后,已发布的定义不会跟着变,要重新打开模型保存并发布。
模板表
BpmProcessExpressionDO 只有名称、状态、表达式三列业务字段。
| 名称 | 说明 | 仓库路径 |
|---|---|---|
name | 列表和弹窗显示名 | BpmProcessExpressionDO |
status | 通用开关,停用后弹窗仍能查到,设计时不要再选 | 同上 |
expression | 最长 1024,原样写入节点 | 同上 |
CREATE TABLE bpm_process_expression (
id bigint NOT NULL AUTO_INCREMENT,
name varchar(64) NOT NULL DEFAULT '',
status tinyint NOT NULL,
expression varchar(1024) NOT NULL,
PRIMARY KEY (id)
);省略创建人、租户等通用列。表注释是「BPM 流程表达式表」。

本系统截图:流程中心 → 流程设置 → 流程表达式。列是名称、状态、表达式;没有模板行时页面仍是这张表,点「新增」写入 bpm_process_expression。
会写到哪里
同一套 UEL,出现在三类位置。
| 名称 | 说明 | 仓库路径 |
|---|---|---|
| 选人规则 | 规则类型选「流程表达式」,参数就是 ${...} | 选择审批人 |
| 完成条件 | 会签 / 或签,如 ${ nrOfCompletedInstances >= nrOfInstances } | 会签、或签、依次审批 |
| 流转条件 | 排他网关出口,如 ${day > 3} | 流程表单设计 |
BpmTaskCandidateExpressionStrategy#calculateUsersByTask 要求表达式结果能转成 Set<Long>。写错成布尔值,选人会空。
预测未走到的节点时,表达式若引用 execution 或不存在的变量,会抛 PropertyNotFoundException。策略吞掉这次异常,预测结果是空集合,不是发布失败。
两个示例 Bean
仓库里还留着两个 @Component,专门给 BPMN 面板当范例。类上都标了 @Deprecated:新图请改用对应的 BpmTaskCandidateStrategy,不要再把选人写成手写表达式。
| 名称 | 说明 | 仓库路径 |
|---|---|---|
| 发起人 | 读 processInstance.startUserId | BpmTaskAssignStartUserExpression;替代 BpmTaskCandidateStartUserStrategy |
| 指定级领导 | level 沿部门 parentId 往上走,取 leaderUserId | BpmTaskAssignLeaderExpression;替代 BpmTaskCandidateStartUserDeptLeaderStrategy |
| 部门来源 | 先看流程变量里的部门,没有再用发起人档案 | BpmProcessVariableUtils.getDeptId |
发起人一级领导写成:
${bpmTaskAssignLeaderExpression.calculateUsers(execution, 1)}level 必须大于 0。找不到部门或上级时返回空集合,节点会按空人兜底处理,见选人篇。
示意图:同一套 ${},选人要用户编号,网关要布尔。不要混用。
配置与操作
管理员在 流程表达式 存可复用字符串,真正生效的是节点上那一串 ${}。选人策略选 60 时,参数就是表达式;网关出口写布尔条件。
改模板行不会自动回写已发布节点。要改运行逻辑,打开模型改节点上的表达式再发布。示例 Bean 已过时,新图用候选人策略。
开启见 流程功能设计。截图见上文列表。
