Flowable bmpn表达式JUEL
一、变量取值与存在判断(var:/variables:/vars: 前缀通用)
1)get / getOrDefault(推荐,防空报错)
${var:get("userDeptIdList")}
${var:getOrDefault("userDeptIdList", "默认部门")}
- 作用:安全获取变量;不存在/
null不抛异常。
2)exists / notExists(判断是否存在且非空)
${var:exists("userDeptIdList")}
${var:notExists("userDeptIdList")}
- 作用:
exists= 非null;notExists=null或不存在。
3)isEmpty / isNotEmpty(空判断,字符串/集合/数组)
${var:isEmpty("userDeptIdList")}
${var:isNotEmpty("userDeptIdList")}
- 字符串:
""算空;集合:size=0 算空;null算空。
二、集合/数组类(你最关心的 contains 家族)
1)contains(集合包含单个元素)
${var:contains(userDeptIdList, "085ebdc83c7f4f11678e1850fa1ce594")}
- 等价 Java:
list.contains(element)
2)containsAny(集合包含任意一个,你之前用的)
${var:containsAny(userDeptIdList, "部门A", "部门B", "部门C")}
- 只要有一个匹配就返回
true
3)containsAll(集合包含全部)
${var:containsAll(userDeptIdList, "部门A", "部门B")}
- 必须全部包含才返回
true
4)size / length(集合/数组大小)
${var:size(userDeptIdList) > 0}
${var:length(userDeptIdList) > 0}
三、字符串处理(flwStringUtils 或 var: 均可)
1)contains(字符串包含子串)
${var:contains(applyReason, "紧急")}
2)startsWith / endsWith
${var:startsWith(orderNo, "ORD-")}
${var:endsWith(orderNo, "-2026")}
3)substring / substringFrom
${flwStringUtils.substring(applyReason, 0, 5)}
${flwStringUtils.substringFrom(applyReason, 2)}
4)split(字符串转集合)
${flwStringUtils.split(deptIds, ",")}
5)toLowerCase / toUpperCase
${var:toLowerCase(username) == "admin"}
四、相等/比较(eq/ne/lt/le/gt/ge)
${var:eq(amount, 1000)} // ==
${var:ne(amount, 1000)} // !=
${var:lt(amount, 1000)} // <
${var:le(amount, 1000)} // <=
${var:gt(amount, 1000)} // >
${var:ge(amount, 1000)} // >=
五、日期常用(内置 date: 前缀)
${date:now()} // 当前日期时间
${date:format(date:now(), "yyyy-MM-dd")}
${date:diffDays(startDate, endDate) > 7}
六、数值常用(math: 或直接写)
${math:abs(amount)}
${math:round(amount, 2)}
${math:max(100,200)}
${math:min(100,200)}
七、逻辑组合(常用在网关条件)
// 且
${var:containsAny(deptList, "D001") && var:gt(amount, 5000)}
// 或
${var:containsAny(deptList, "D001") || var:gt(amount, 5000)}
// 非
${!var:containsAny(deptList, "D001")}
常用速查表(直接复制)
| 函数 | 作用 | 示例 |
|---|---|---|
var:get(var) |
安全取值 | ${var:get("deptList")} |
var:isEmpty(var) |
是否空 | ${var:isEmpty("deptList")} |
var:contains(list, e) |
集合含元素 | ${var:contains(deptList, "D1")} |
var:containsAny(list, e1,e2) |
含任意一个 | ${var:containsAny(deptList, "D1","D2")} |
var:containsAll(list, e1,e2) |
含全部 | ${var:containsAll(deptList, "D1","D2")} |
var:eq(a,b) |
等于 | ${var:eq(amount, 1000)} |
var:gt(a,b) |
大于 | ${var:gt(amount, 1000)} |
扩展篇
一、JUEL 是什么(一句话)
JUEL = Java Unified Expression Language,是 Java EE UEL(统一表达式语言) 的一个轻量、高性能、可缓存的开源实现。
- 标准:遵循 JSP 2.1 / JSR-245,兼容 Java EE 5/6。
- 包:
javax.el,由 de.odysseus.juel 提供实现。 - 特点:体积小、速度快、支持方法调用、自带缓存、可扩展函数。
二、JUEL 和 Flowable 的关系(重点)
Flowable 默认表达式引擎就是 JUEL。
你在 BPMN 里写的:
- 网关条件:
${var:containsAny(...)} - 负责人:
${assignee} - 跳过表达式:
${leaveDays <= 1} - 任务监听器/执行监听器表达式
全都是 JUEL 表达式。
Flowable 内置了一套 JUEL 扩展函数(就是你上一问看到的 var:xxx、date:xxx、math:xxx),底层是 JUEL 解析执行。
三、JUEL 基础语法(你每天都在用)
1)基本格式
${表达式}
- 引擎会把
${}里面的内容交给 JUEL 解析计算。
2)变量访问
${userDeptIdList} // 直接取流程变量
${order.amount} // 取对象属性
${list[0]} // 取集合元素
3)运算
${amount > 1000}
${a + b * 2}
${empty userDeptIdList} // 判断 null/空字符串/空集合
4)方法调用(JUEL 强于原生 EL)
${str.length()}
${list.contains("xxx")}
${date.getTime()}
四、Flowable 对 JUEL 的扩展(最常用)
Flowable 在标准 JUEL 上包装了一套内置函数,用前缀区分:
1)var: (变量/集合操作)
${var:contains(list, e)}
${var:containsAny(list, e1,e2)}
${var:isEmpty(list)}
${var:getOrDefault("key", def)}
2)date: (日期)
${date:now()}
${date:format(date, "yyyy-MM-dd")}
${date:diffDays(d1, d2)}
3)math: (数值)
${math:abs(n)}
${math:round(n,2)}
4)flwStringUtils: (字符串)
${flwStringUtils.split(str, ",")}
${flwStringUtils.substring(str,0,5)}
五、JUEL vs 原生 EL vs Groovy/JS(选型)
1)JUEL vs 原生 EL
- 原生 EL:功能弱,不支持方法调用,性能一般。
- JUEL:支持方法调用、缓存、高性能、可扩展,Flowable 首选。
2)JUEL vs Groovy/JavaScript
Flowable 支持三种脚本,场景不同:
| 维度 | JUEL | Groovy / JS |
|---|---|---|
| 适用 | 简单条件、变量访问 | 复杂逻辑、循环、调用 Bean |
| 性能 | 极高(毫秒级) | 较低(脚本引擎开销) |
| 安全 | 沙箱可控,无注入风险 | 风险高,可执行任意代码 |
| 调试 | 难 | 较易 |
| 推荐场景 | 网关条件、任务分配、简单判断 | 脚本任务、复杂计算、服务调用 |
一句话:能用 JUEL 就用 JUEL,复杂逻辑再用 Groovy。
六、你之前的表达式,用 JUEL 原生怎么写?
你原来的:
${var:containsAny(userDeptIdList,"085ebdc83c7f4f11678e1850fa1ce594")}
去掉 Flowable 扩展,纯 JUEL 原生写法(前提:userDeptIdList 是 List):
${userDeptIdList.contains("085ebdc83c7f4f11678e1850fa1ce594")}
Flowable 的 var:containsAny 本质就是对这种原生方法的封装和容错(比如判空)。
七、小结(记住这 3 点)
- JUEL 是 EL 的高性能实现,Flowable 默认表达式引擎。
- ${...} 全是 JUEL,Flowable 加了
var:/date:/math:扩展。 - 简单条件用 JUEL,复杂逻辑用 Groovy。