一、变量取值与存在判断(var:/variables:/vars: 前缀通用)

1)get / getOrDefault(推荐,防空报错)

${var:get("userDeptIdList")}
${var:getOrDefault("userDeptIdList", "默认部门")}
  • 作用:安全获取变量;不存在/null 不抛异常。

2)exists / notExists(判断是否存在且非空)

${var:exists("userDeptIdList")}
${var:notExists("userDeptIdList")}
  • 作用:exists = 非 nullnotExists = 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:xxxdate:xxxmath: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 点)

  1. JUEL 是 EL 的高性能实现,Flowable 默认表达式引擎
  2. ${...} 全是 JUEL,Flowable 加了 var:/date:/math: 扩展。
  3. 简单条件用 JUEL,复杂逻辑用 Groovy