lczCreater中的表达式按照执行时机的不同,分为后台表达式(由后台java程序执行的、在取数后初始阶段执行的、在数据提交到数据库时相关的)和前台表达式(数据加载到Web页面后,由前端初始渲染或交互过程中执行的)。

本文档重点介绍后台表达式的语法及相关业务示例,方便用户学习借鉴。

1 什么是JUEL表达式?

JUEL 是统一表达式语言(Unified Expression Language , EL )在Java应用环境下的一个实现。
其中,函数采用的是java函数语法。

JUEL也是一种模板语言,以${起始,}结尾,其中的内容便是要计算替换的内容,其他的内容是常量。例如:

乐创者${产品名称}是一种低代码、高效的${产品类型}设计神器,可帮助业务人员通过简单的配置即可快速搭建专业Web系统的开发平台。

上面的内容即是一个JURL表达式,当 ${产品名称}值为“跨设备表单”,${产品类型}值为“Web表单”时,表达式运算后的结果为:

乐创者跨设备表单是一种低代码、高效的Web表单设计神器,可帮助业务人员通过简单的配置即可快速搭建专业Web系统的开发平台。

lczCreater表达式是基于JUEL表达式的基础上扩展而来的,并在其基础上扩展了一些业务函数。

术语解释:

元数据:乐创者中,对数据库表结构定义信息的一种扩充对象,用于描述字段在页面中的呈现控件、数值格式、解码数据来源等。
字段标识:在元数据中定义的,用于唯一标识字段的名称;可以有效防止前后端数据交互时,对数据库表结构的暴露;

2 应用范围

在跨设备表单(lczCreater)相关的对象(跨设备表单模板、元数据、CodeTable、EasySearch、流程表单及相关对象等)中很多属性都支持脚本解析,其遵循的就是JUEL语法,这里就不一一列举了。
也有一部分特殊的表达式是由前台Web页面执行的,遵循的是javascript语法(不适用本文档规则),如:
1)跨设备表单中的表达式->公式计算;
2)跨设备表单中的表达式->动态显示;
3)跨设备表单中的表达式->保存校验;
4)工作流表单中的表达式->保存校验;

3 上下文对象说明

在lczCreater的表达式中,要获取表中某行中字段的值或对字段进行聚合计算时,通常需要通过行上下文对象。

3.1 数据集

数据集上下文对象:dataset
一般在做聚合计算时使用。

3.2 行

行上下文对象:row、mainRow
编写表达式的所属对象不同,行上下文对象有所不同,其大致规则如下:
在同一表内编写的表达式,获取字段的值时,行上下文对象为:row,例如:元数据中的控件默认值表达式、控件默认值表达式等
在表外编写的表达式,获取字段的值时,行上下文对象为:mainRow,例如:流程表单中,流程标题、发起校验条件表达式、提交检验条件表达式等

4 获取字段值

4.1 获取表内字段值

适用于所有模型中,获取表内字段值。

${row.getValue("字段标识")}

row.getValue的返回值为一个Object对象,Object的类型根据数据库字段类型确定;
例如:数据库字段类型为字符型、text等类型时,返回值为String类型的字符串对象;其他情况如下表所示:

数据库字段类型 字段返回值的Java类型 元数据类型
varchar String 字符型
text String 长文本
int Int 整型
bigint Long 长整型
double Double 双精度浮点型
smallint Short 整型
decimal BigDecimal 实数型
datetime Date 日期时间
date Date 日期

目前仅支持以上数据类型,其余类型暂不支持。

关于getValue这个方法的说明:
getValue除了拿取指定字段的值意外还附带了特殊的逻辑(即getValue返回的对象不会为null):
1)如果获取的字段不存在,自动返回空字符串””
2)如果获取的值为空(DbNull即数据库为null),自动返回空字符串””

如果要进行数值比较,则需要在getValue的外面使用转换函数进行处理,例如:
假设字段1和字段2进行大小比较,这两个字段的类型都为整型值(int),值可能为null,那么,表达式应该为:${safeInt(row.getValue("字段1")) > safeInt(row.getValue("字段2"))},而不是:${row.getValue("字段1") > row.getValue("字段2")}

4.2 获取主表字段值

适用于主从模型、多对多模型中,从表获取主表字段值。

${mainRow.getValue("字段标识")}

5 操作符

5.1 算数操作符

适用于两个数值(整型、双精度、浮点型等)进行加减乘除求余计算:

+ : 适用于两个数值相加,例如: 4 + 5${row.getValue("字段标识") + 10}

- : 适用于两个数值相减,例如: 5 - 4${row.getValue("字段标识") - 10}

* : 适用于两个数值相乘,例如: 4 * 5${row.getValue("字段标识") * 10}

/ : 适用于两个数值相除,例如: 5 / 4${row.getValue("字段标识") / 10}

% : 适用于两个数值求余,例如: 54 % 5${row.getValue("字段标识") % 10}

5.2 关系操作符

适用于两个数值(整型、双精度、浮点型等)、日期、日期时间等类型的比较,比较的结果是布尔型值(true / false):

< : 小于, 例如: ${row.getValue("字段1") < row.getValue("字段1")}

<= : 小于等于, 例如: ${row.getValue("字段1") <= row.getValue("字段2")}

> : 大于, 例如: ${row.getValue("字段1") > row.getValue("字段2")}

>= : 大于等于, 例如: ${row.getValue("字段1") >= row.getValue("字段2")}

== : 等于, 例如: ${row.getValue("字段1") == row.getValue("字段2")}

!= : 不等于, 例如: ${row.getValue("字段1") != row.getValue("字段2")}

5.3 逻辑操作符

5.3.1 逻辑非

主要用于布尔值的取反操作:

! : 值取反

例如: !${row.getValue("字段标识")},假设字段1的值是true,那么表达式的值为:false

5.3.2 逻辑与

一般用于布尔值的与操作:

&& : 适用于两个值相与

例1: ${row.getValue("字段1") && row.getValue("字段2")},假设字段1的值是true,字段2的值是false,那么表达式的值为:false

例2:${1 && 0},那么表达式的值为:false

例3:${1 && 2},那么表达式的值为:true

注意:字符值的值不要直接进行逻辑与操作,应先转换为数值后再进行逻辑与操作;

5.3.3 逻辑或

一般用于布尔值的或操作:

|| : 适用于两个值相或

例1: ${row.getValue("字段1") || row.getValue("字段2")},假设字段1的值是true,字段2的值是false,那么表达式的值为:true
例2:${1 || 0},那么表达式的值为:true
例3:${1 || 2},那么表达式的值为:true

注意:字符值的值不要直接进行逻辑或操作,应先转换为数值后再进行逻辑或操作;

6 表达式运算

6.1 字符串运算

1)字符串拼接
例如:要显示某条记录的创建人、创建时间

创建人:${row.getValue("CreateId")}

创建时间:${format("yyyy年MM月dd日 HH时mm分ss秒",row.getValue("CreateDate"))}

2)字符串比较是否相同
例如:判定字段的值是否等于”表单”

//大小写敏感
${row.getValue("字段标识").equals("表单")}

//忽略大小写
${row.getValue("字段标识").equalsIgnoreCase("表单")}

3)判空

//无关类型判断是否为空:
${isEmpty(row.getValue("字段标识"))}

//将数据转换成字符串,判定是否等于空字符串:
${row.getValue("字段标识").toString()==""}

4)包含,起始,结束

//包含:
${row.getValue("字段标识").contains("包含值")}

//起始:
${row.getValue("字段标识").startsWith("起始值")}

//结束:
${row.getValue("字段标识").endsWith("结束值")}

5)剔除字符串两边空格

//去掉字符串两端的空格
${row.getValue("字段标识").trim()}

6)字符串转大写小写

//大写输出
${row.getValue("字段标识").toUpperCase()}

//小写输出
${row.getValue("字段标识").toLowerCase()}

6)字符串替换

//替换为指定字符串:
${row.getValue("字段标识").replaceAll("被替换的字符串","指定字符串")}

例如:
${"abcdddd".replaceAll("d","e")}  //输出为:"abceeee"

6.2 数值运算

对于数值字段的加减乘除等运算中,使用到字段值的,我们要注意对null值的处理。
如果字段返回的数值不会返回null(如数据库字段不允许为null的),获取字段值直接使用;
如果字段返回的数值存在null的,获取字段值后,要做转换处理才能使用。

1)简单的加减乘除运算

//字段不存在NULL的:
${row.getValue("字段标识1")+row.getValue("字段标识2")}
//字段存在NULL的,整型数值相加:
${safeShort(row.getValue("字段标识1"))+safeShort(row.getValue("字段标识2"))}
${safeInt(row.getValue("字段标识1"))+safeInt(row.getValue("字段标识2"))}
${safeLong(row.getValue("字段标识1"))+safeLong(row.getValue("字段标识2"))}
//字段存在NULL的,非整型数值相加:
${safeDouble(row.getValue("字段标识1"))+safeDouble(row.getValue("字段标识2"))}
${safeFloat(row.getValue("字段标识1"))+safeFloat(row.getValue("字段标识2"))}

2)数值比较
例如:判定字段值大于1000,返回true,否则返回false:

//返回不存在NULL的
${row.getValue("字段标识1") > 1000 ? true : false} 
//返回存在NULL的
${safeInt(row.getValue("字段标识1")) > 1000 ? true : false} //先转换为int类型
${safeDouble(row.getValue("字段标识1")) > 1000 ? true : false} //先转换为double类型

3)判空

//无关类型判断是否为空
${isEmpty(row.getValue("字段标识"))}
//将数据转换成字符串,判定是否等于空字符串
${row.getValue("字段标识").toString()==""}

6.3 日期运算

1)获取当前年份,月份,日期

${year()}  //返回今年年份,如:2021
${month()} //返回当月月份,如:04
${now()} //返回当前时间,如:2021-04-14 10:09:01
${lastMonthDay()} //返回当前月份的最后一天,如:2021-04-30
${lastWeekDay()} //返回当前周的最后一天,如:2021-04-18
${lastWorkDay()} //返回当前周的最后一个工作日(周五),如:2021-04-16
(如果当前日期是周六,拿到的日期是本周的周五)

注意:以上返回的都是字符串,不是日期类型,无法直接与日期类型进行比较

2)格式化字段日期数据

${format("yyyy年MM月dd日",row.getValue("日期字段"))}
${format("yyyy-MM-dd",row.getValue("日期字段"))}
${format("yyyy/MM/dd",row.getValue("日期字段"))}
${format("yyyy年MM月dd日 HH时mm分ss秒",row.getValue("日期时间字段"))}
${format("yyyy/MM/dd HH:mm:ss",row.getValue("日期时间字段"))}

3)比较日期大小

//左边的参数值必须是日期或者日期时间类型,不能是字符类型,右边的参数可以是日期或者字符,都可以
${greatThan(row.getValue("日期时间字段"),"2021-01-22")}
${lessThan(row.getValue("日期时间字段"),"2021-01-22")}
${greatEqualThan(row.getValue("日期时间字段"),"2021-01-22")}
${lessEqualThan(row.getValue("日期时间字段"),"2021-01-22")}

//日期类型如果需要做等于判定推荐格式化后使用字符串的equals
${"2021-04-14".equals(format("yyyy-MM-dd",row.getValue("日期字段")))}

4) 计算月截止日期
通过日期值精确到年月格式(yyyy-MM)的字符串值,如何获取当月的截止日期?

假设从参数"year_month"中获得参数值,转换表达式为:
${format("yyyy-MM-dd",lastDay(parseDate("yyyy-MM",lczServer:searchConfig('year_month')),"MONTH",0))}

6.4 聚合运算

6.4.1 求和

返回对象为BigDecimal(实数)(空值或者非数值类数据做0计算)

sum(Object valueProvider, String tableName, String fieldName)

参数
valueProvider:一般指代dataSet数据集合,写死dataSet即可
tableName:表名,需要获取数据的表名
fieldName:需要聚合的字段名称

返回值
BigDecimal类型的实数,可以直接转换成文本,也可用于大于小于判定

举例

//返回table1的field1字段的累加和是否大于100:
${sum(dataSet,"表名","字段名")>100}

6.4.2 获取最大值

返回对象为BigDecimal(实数)(空值或者非数值类数据做0计算,无数据时为0)

max(Object valueProvider, String tableName, String fieldName)

参数
valueProvider:一般指代dataSet数据集合,写死dataSet即可
tableName:表名,需要获取数据的表名
fieldName:需要聚合的字段名称

返回值
BigDecimal类型的实数,可以直接转换成文本,也可用于大于小于判定

举例

//返回table1的field1字段的最大值是否大于100:
${max(dataSet,"表名","字段名")>100}

6.4.3 获取最小值

返回对象为BigDecimal(实数)(空值或者非数值类数据做0计算,无数据时为0)

min(Object valueProvider, String tableName, String fieldName)

参数
valueProvider:一般指代dataSet数据集合,写死dataSet即可
tableName:表名,需要获取数据的表名
fieldName:需要聚合的字段名称

返回值
BigDecimal类型的实数,可以直接转换成文本,也可用于大于小于判定

举例

//返回table1的field1字段的最小值是否大于100:
${min(dataSet,"表名","字段名")>100}

6.4.4 获取平均值

返回对象为BigDecimal(实数)(空值或者非数值类数据做0计算,保留两位小数,四舍五入)

avg(Object valueProvider, String tableName, String fieldName)

参数
valueProvider:一般指代dataSet数据集合,写死dataSet即可
tableName:表名,需要获取数据的表名
fieldName:需要聚合的字段名称

返回值
BigDecimal类型的实数,可以直接转换成文本,也可用于大于小于判定

举例

//返回table1的field1字段的平均值是否大于100:
${avg(dataSet,"表名","字段名")>100}

6.4.5 计数

返回对象为long(长整型)(空值数据不计数)

count(Object valueProvider, String tableName, String fieldName)

参数
valueProvider:一般指代dataSet数据集合,写死dataSet即可
tableName:表名,需要获取数据的表名
fieldName:需要聚合的字段名称

返回值
long类型的长整数,可以直接转换成文本,也可用于大于小于判定

举例

//返回table1的field1字段的总数是否大于100:
${count(dataSet,"表名","字段名")>100}

6.5 三元条件运算

在需要进行一些判定校验时,可以使用三元运算符

条件值 ? 满足值 : 不满足值

${safeDouble(row.getValue("字段标识")) > 100000 ? truefalse}

附录、返回字段值相关java对象常用方法

String对象

1、求字符串长度

int length() 返回该字符串的长度,例如:${“字段标识”.length()}

2、求字符串某一位置字符

char charAt(int index) 返回字符串中指定位置的字符;注意字符串中第一个字符索引是0,最后一个是length()-1。

3、提取子串

用String类的substring方法可以提取字符串中的子串,该方法有两种常用参数:

1) String substring(int beginIndex) 该方法从beginIndex位置起,从当前字符串中取出剩余的字符作为一个新的字符串返回。

2) String substring(int beginIndex, int endIndex) 该方法从beginIndex位置起,从当前字符串中取出到endIndex-1位置的字符作为一个新的字符串返回。

4、字符串比较

1) int compareTo(String anotherString) 该方法是对字符串内容按字典顺序进行大小比较,通过返回的整数值指明当前字符串与参数字符串的大小关系。若当前对象比参数大则返回正整数,反之返回负整数,相等返回0。

2) int compareToIgnore(String anotherString) 与compareTo方法相似,但忽略大小写。

3) boolean equals(Object anotherObject) 比较当前字符串和参数字符串,在两个字符串相等的时候返回true,否则返回false。

4) boolean equalsIgnoreCase(String anotherString) 与equals方法相似,但忽略大小写。

5、字符串连接

String concat(String str) 将参数中的字符串str连接到当前字符串的后面,效果等价于”+”。

6、字符串中字符的大小写转换

1) String toLowerCase() 返回将当前字符串中所有字符转换成小写后的新串

2) String toUpperCase() 返回将当前字符串中所有字符转换成大写后的新串

7、字符串中字符的替换

1) String replace(char oldChar, char newChar) 用字符newChar替换当前字符串中所有的oldChar字符,并返回一个新的字符串。

2) String replaceFirst(String regex, String replacement) 该方法用字符replacement的内容替换当前字符串中遇到的第一个和字符串regex相匹配的子串,应将新的字符串返回。

3) String replaceAll(String regex, String replacement) 该方法用字符replacement的内容替换当前字符串中遇到的所有和字符串regex相匹配的子串,应将新的字符串返回。

8、其他方法

1) String trim() 截去字符串两端的空格,但对于中间的空格不处理。

2) boolean startsWith(String prefix)boolean endWith(String suffix) 用来比较当前字符串的起始字符或子字符串prefix和终止字符或子字符串suffix是否和当前字符串相同,重载方法中同时还可以指定比较的开始位置offset。

3) boolean regionMatches(boolean b, int firstStart, String other, int otherStart, int length) 从当前字符串的firstStart位置开始比较,取长度为length的一个子字符串,other字符串从otherStart位置开始,指定另外一个长度为length的字符串,两字符串比较,当b为true时字符串不区分大小写。

4) boolean contains(String str) 判断参数s是否被包含在字符串中,并返回一个布尔类型的值。

5) String[ ] split(String str) 将str作为分隔符进行字符串分解,分解后的字字符串在字符串数组中返回。

Double对象

1) boolean isNaN() 如果此值是一个非数字 (NaN) 值,则返回 true,否则返回false。

2) boolean isInfinite() 如果此对象表示的值是正无穷大或负无穷大,则返回 true;否则返回false。

3) String toString() 输出字符串值

4) byte byteValue() 输出byte值

5) byte shortValue() 输出short值

6) byte intValue() 输出int值

7) byte longValue() 输出long值

8) byte floatValue() 输出float值

9) byte doubleValue() 输出double值

10) int compareTo(Double anotherDouble) 比较数值大小

如果当前值与参数值等返回 0。
如果当前值小于参数值返回 -1。
如果当前值大于参数值返回 1。如果当前值大于参数值返回 1。

Date对象

1) int getYear() 返回年份,需要加 1900

2) int getMonth() 返回月份 0~11,需要加 1

3) int getDate() 返回表示的月份中的某天

4) int getDay() 返回此日期代表的星期几

5) int getHours() 返回小时

6) int getMinutes() 返回分

7) int getSeconds() 返回秒

8) long getTime() 返回毫秒数

9) boolean before(Date when) 测试此日期是否在指定日期之前。

10) boolean after(Date when) 测试此日期是否在指定日期之后。

11) int compareTo(Date anotherDate) 比较日期时间大小

如果当前值与参数值等返回 0。
如果当前值小于参数值返回 -1。
如果当前值大于参数值返回 1。如果当前值大于参数值返回 1。

12) String toString() 转化为字符串对象值

作者:Eric  创建时间:2023-06-07 17:07
最后编辑:Eric  更新时间:2025-04-24 13:55