【工作实践】MVEL 2.x语法指南

news2024/12/22 23:55:07

目录标题

  • MVEL 2.x语法指南
  • 一、基本语法
    • 1. 简单属性表达式
    • 2. 复合语句
    • 3. 返回值
  • 二、值判断
    • 1. 判断空值
    • 2. 判断Null值
    • 3. 强制转换
  • 三、内联Lists、Maps和数组Arrays
    • 1. Lists
    • 2. Maps
    • 3. 数组Arrays
    • 4. 数组强制转换
  • 四、属性导航
    • 1. Bean属性
    • 2. Bean的安全属性导航
    • 3. 集合
      • (1). List的访问
      • (2). Map的访问
    • 4. 字符串作数组
  • 五、文字常量
    • 1. 字符串常量
      • 字符串转义字符
    • 2. 数字常量
    • 3. 浮点型常量
    • 4. 大数字常量
    • 5. 布尔常量
    • 6. 空常量
  • 六、类型常量
    • 嵌套类类
  • 七、流程控制
    • 1. If-Then-Else
    • 2. 三目运算符
    • 3. Foreach
    • 4. for循环
    • 5. Do While, Do Until
    • 6. While, Until
  • 八、投影和交集
  • 九、赋值
  • 十、函数定义
    • 1. 一个简单示例
    • 2. 传参和返回值
    • 3. 闭包
  • 十一、Lambda表达式
  • 十二、工作实践

在这里插入图片描述

MVEL 2.x语法指南

MVEL全称为:MVFLEX Expression Language,是用来计算Java语法所编写的表达式值的表达式语言。MVEL的语法很大程度上受到Java语法的启发,但为了使表达式语法更高效,还是有一些基本差异,例如可以像正则表达式一样直接支持集合、数组和字符串匹配的运算。

除了表达式语言之外,MVEL还用作配置和字符串构造的模板语言。

MVEL 2.x表达式主要包括以下特性:

  • 属性表达式
  • 布尔表达式
  • 方法调用
  • 变量赋值
  • 函数定义

一、基本语法

MVEL是基于Java语法的表达式语言,具有特定于MVEL的一些明显差异。与Java不同,MVEL是动态类型化(可选类型化),意味着在源代码中不需要类型限定。

MVEL可以方便的集成到产品中使用。Maven的集成方式如下:

<dependency>
    <groupId>org.mvel</groupId>
    <artifactId>mvel2</artifactId>
    <version>2.2.8.Final</version>
</dependency>

一个MVEL表达式,简单的可以是单个标识符,复杂的则可能是一个充满了方法调用和内部集合创建的庞大的布尔表达式。使用MVEL提供的API。可以动态得到表达式的执行结果。

1. 简单属性表达式

user.name

在这个表达式中,我们只有一个标识符(user.name),在MVEL中我们称它为属性表达式,因为表达式的唯一目的就是从上下文中提取出变量或者对象的属性。属性表达式是最常见的用途之一,通过它,MVEL可以用来作为一个高性能,易使用的反射优化器。

MVEL甚至可以用来计算布尔表达式:

user.name =='John Doe'

与Java一样,MVEL支持所有优先级规则,包括通过括号来控制执行顺序。

(user.name == 'John Doe') && ((x * 2) - 1) > 20

2. 复合语句

您可以使用分号来表示语句的终止,使用任意数量的语句编写脚本。分号在所有情况下都是必需的,除非在脚本中只有一个语句或最后一个语句。

statement1; statement2; statement3

注意:statement3语句后可以缺少分号。

另外,换行不能替代分号来作为一个语句的结束标识。

3. 返回值

MVEL是被设计为一个集成语言作为核心,允许开发人员提供简单的脚本设置绑定和逻辑。因此,MVEL表达式使用“last value out”原则(输出最后值原则)。这意味着,尽管MVEL支持return关键字,但却没必要使用它。例如:

a = 10;
b = (a = a * 2) + 10;
a;

在该示例中,表达式返回a的值,因为a;是表达式的最后一个值。它在功能上与下面的脚本等价:

a = 10;
b = (a = a * 2) + 10;
return a;

二、值判断


在MVEL中所有的判断是否相等,都是对值的判断,而没有对引用的判断,因此表达式foo == 'bar'等价于Java中的foo.equals("bar")

1. 判断空值

MVEL提供了一个特殊的字符来表示值为空的情况,叫作empty,例如:

foo == empty

若foo满足空的任何条件,这个表达式值都为true。

2. 判断Null值

MVEL中,nullnil都可以用来表示一个Null值,如:

foo == null;
foo == nil; // 和null一样

3. 强制转换

当两个不同类型且没有可比性的值进行比较时,MVEL会应用类型强制转换系统,即将左边的值强制转换成右边的值的类型,反之亦然。如:

"123" == 123;

这个表达式的值为true,因为为了执行比较,强制类型转换系统会隐式的将数字123转换成字符串。

三、内联Lists、Maps和数组Arrays


MVEL允许你使用简单优雅的语法来表示Lists,Mpas和数组Arrays。 且看下面的示例:

["Bob" : new Person("Bob"), "Michael" : new Person("Michael")]

这个表达式的功能等价于:

Map map = new HashMap();
map.put("Bob", new Person("Bob"));
map.put("Michael", new Person("Michael"));

用这种结构描述MVEL内部数据结构,功能非常强大,你可以在任何地方使用它,甚至可以作为方法的参数使用,如:

something.someMethod(["foo" : "bar"]);

1. Lists

Lists用以下格式来表示:”[item1, item2, …]”,如:

["Jim", "Bob", "Smith"]

2. Maps

Maps用以下格式来表示:”[key1 : value1, key2: value2, …]”,如:

["Foo" : "Bar", "Bar" : "Foo"]

3. 数组Arrays

数组Arrays用以下格式来表示:”{item1, item2, …}”,如:

{"Jim", "Bob", "Smith"}

4. 数组强制转换

关于内联数组,需要知道的一个非常重要的方面是,它可以被强制转换成其它类型的数组,当你声明一个数组时,是不直接指定其类型的,但你可以通过将其传递给一个接收int[]类型参数的方法来指定。如:

foo.someMethod({1,2,3,4});

在这种情况下,当MVEL发现目标方法接收的是一个int[],会自动的将{1,2,3,4}转换成int[]类型。

四、属性导航


MVEL属性导航遵循在其他语言(如Groovy,OGNL,EL等)中bean属性表达式中公认惯例的使用方式。和其它语言必须通过底层的方法来控制权限不同的是,MVEL提供了一种单一的,统一的语法来访问属性,静态字段和maps等。

1. Bean属性

大多数java开发者都熟悉getter/setter模式,并在java对象中用它来封装属性的访问权限。例如,你可能会通过下面的方式访问一个对象的属性:

user.getManager().getName();

为了简化此操作,您可以使用以下表达式访问相同的属性:

user.manager.name

注意:当一个对象中的字段的作用域是public时,MVEL仍然倾向于通过get方法来访问其属性。

2. Bean的安全属性导航

有时,当你的表达式中会含有null元素时,这时就需要你进行一个为空判断,否则就会发生错误。当你使用null-safe操作符时你可以简化这个操作:

user.?manager.name

它的功能相当于:

if (user.manager != null) { return user.manager.name; } else { return null; }

3. 集合

集合的遍历也可以通过简单的语法来实现:

(1). List的访问

List可以像访问数组一样访问,如:

user[5]

这等价与java中的代码:

user.get(5);

(2). Map的访问

Map的访问和访问数组也非常相似,不同的是,在访问Map时索引值可以是任意对象,如:

user["foobar"]

这等价与java中的代码:

user.get("foobar");

当Map的key是String类型时,还可以使用特殊的方式来访问,如:

user.foobar

4. 字符串作数组

为了能使用属性的索引(迭代也是如此),所有的字符串都可以看成是一个数组,在MVEL中你可以用下面的方式来获取一个字符串变量的第一个字符:

foo = "My String";
foo[0]; // returns 'M'

五、文字常量


在脚本语言中,一段文字(常量)用来代表一个固定的值。

1. 字符串常量

字符串常量可以用一对单引号或一对双引号来界定。如:

"This is a string literal"
'This is also string literal'

字符串转义字符

  • \ - 代表一个反斜杠。
  • \n - 换行符
  • \r - 回车符
  • \u#### - Unicode字符 (如: /uAE00)
  • ### - 八进制字符 (如: /73)

2. 数字常量

整数可以表示为十进制(基数为10),8进制(基数为8),或十六进制(基数为16)。

一个十进制数字,不从零开始(相对于8进制、16进制而言),可以表示任意数,如:

125 // 十进制

一个八进制数,以0为前缀,后面跟着0到7内的数字。

0353 // 八进制

一个十六进制,以0X为前缀,后面可以跟着0-9,A-F范围内的数字。

0xAFF0 // 十六进制

3. 浮点型常量

浮点数由整数和由点/周期字符表示的小数部分组成,带有可选的类型后缀。

10.503 // double型
94.92d // double型
14.5f // float型

4. 大数字常量

您可以使用后缀B和I(必须大写)来表示BigDecimal和BigInteger文字,如:

104.39484B // BigDecimal
8.4I // BigInteger

5. 布尔常量

布尔型常量用保留关键字true和false来表示。

6. 空常量

用null或nil来表示。

六、类型常量


类型常量的处理方式与Java中的相同,格式为:”.“。

所以一个类可以这样限定:

java.util.HashMap

或者如果类已经通过或者通过外部配置被导入,则它被简单地通过其非限定名称来引用:

HashMap

嵌套类类

嵌套类不能通过MVEL 2.0中的标准点表示法(如Java中)来访问。 相反,你必须用$符号限定这些类。

org.proctor.Person$BodyPart

七、流程控制


MVEL的强大已经超出了简单的表达式。事实上,MVEL提供了一系列的程序流程控制操作符来方便你进行高级的脚本操作。

1. If-Then-Else

MVEL提供了完整的C/Java式的if-then-else块,如:

if (var > 0) {
   System.out.println("Greater than zero!");
} else if (var == -1) { 
   System.out.println("Minus one!");
} else { 
   System.out.println("Something else!");
}

2. 三目运算符

其实就是Java中的条件表达式,如:

var > 0 ? "Yes" : "No";

可以嵌套三目运算符

var > 0 ? "Yes" : (var == -1 ? "Minus One!" : "No")

3. Foreach

MVEL的强大特性之一就是其Foreach操作符,在功能和语法上,他都类似于java1.5中的for each操作符,它接收用冒号隔开的两个参数,第一个是当前元素的一个域变量,而第二个是要迭代的集合或数组。如下所示:

count = 0;
foreach (name : people) {
   count++;
   System.out.println("Person #" + count + ":" + name);
}

System.out.println("Total people: " + count);

因为MVEL将字符串视作一个可以迭代的对象,所以你可以用foreach语句来迭代一个字符串(一个字符接一个字符的):

str = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";

foreach (el : str) {
   System.out.print("["+ el + "]"); 
}

上面的示例将会输出:

[A][B][C][D][E][F][G][H][I][J][K][L][M][N][O][P][Q][R][S][T][U][V][W][X][Y][Z]

你也可以利用MVEL进行计数(从1开始):

foreach (x : 9) { 
   System.out.print(x);
}

这会输出:

123456789

注意 : 像java5.0一样,在MVEL2.0中,可以将foreach简化成关键字for来使用,如:

for (item : collection) { ... }

4. for循环

MVEL实现了标准的C语言的for循环:

for (int i =0; i < 100; i++) { 
   System.out.println(i);
}

5. Do While, Do Until

和java中的意义一样,MVEL也实现了Do While,Do Until,While和Until意义正好相反。

do { 
   x = something();
} 
while (x != null);

在语义上相当于:

do {
   x = something();
}
until (x == null);

6. While, Until

MVEL中实现了标准的While,并添加了一个与之相反的Until。

while (isTrue()) {
   doSomething();
}

或者写成

until (isFalse()) {
   doSomething();
}

八、投影和交集


简单地说,投影是一种描述集合的方式。 通过非常简单的语法,您可以检索集合中非常复杂的对象模型。

假设,你有一个User对象的集合。 每个对象都有一个Parent。 现在你想获得集合users中的所有parent的name的列表(假设Parent中有字段name),你可以这样来写:

parentNames = (parent.name in users);

您甚至可以执行嵌套操作,假设,User对象有个集合成员叫做familyMembers,现在我们想获得一个所有家庭成员姓名的集合:

familyMembers = (name in (familyMembers in users));

九、赋值


MMVEL允许你对表达式中的变量进行赋值,以便在运行时获取,或在表达式内部使用。因为MVEL是动态类型语言,所以你不必为了声明一个变量而指定其类型。当然,你也可以选择指定。

str =My String; // valid
String str =My String; // valid

与java语言不同的是,当给一个指定类型的变量赋值时,MVEL会提供自动的类型转换(可行的话),如:

String num = 1;
assert num instanceof String&amp;&amp; num ==1;

对于动态类型变量而言,你要想对其进行类型转换,你只需要将值转换成相应的类型既可:

num =String1;
assert num instanceof String&amp;&amp; num ==1;

十、函数定义


MVEL可以使用def或function关键字来定义本地函数。

函数必须是先声明后引用,唯一例外的是递归调用的时候。

1. 一个简单示例

定义一个简单函数:

def hello() { System.out.println("Hello!"); }

定义了一个没有参数的函数hello.当调用该函数时会在控制台打印”Hello!” 一个MVEL定义的函数就像任何常规的方法调用。

hello(); // 调用函数

2. 传参和返回值

函数可以接收参数和返回一个值,看下面的示例:

def addTwo(a, b) { 
   a + b;
}

这个函数会接收两个参数(a和b),然后将这两个变量相加。因为MVEL遵循last-value-out原则,所以结果将会被返回。因此,你可以这样来使用这个函数:

val = addTwo(5, 2);
assert val == 10;

当然,也可以使用return关键字来强制从程序内部返回一个函数值。

3. 闭包

MVEL支持闭包,然而其功能与本地java函数没有任何关联。

// 定义一个接收一个参数的函数
def someFunction(f_ptr) { f_ptr(); }

// 定义变量a
var a = 10;

// 传递函数闭包
someFunction(def { a * 10 });

十一、Lambda表达式


MVEL允许定义Lambda方法,如下所示:

threshold = def (x) { x >= 10 ? x : 0 };
result = cost + threshold(lowerBound);

上面的例子定义了一个Lambda,并将其赋值给变量”threshold”.Lambda实质上就是一个用来给变量赋值的函数,也是闭包。

翻译原文:http://mvel.documentnode.com/

十二、工作实践

实践:【工作实践】MVEL2.0快速上手

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2080871.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

BOSS AI

BOSS AI 人工智能一点也不智能啊&#xff0c;机器人都不考虑用户的需求和体验吗&#xff1f; 这么多&#xff0c;我怎么看&#xff0c;我也不知道对面是人呢&#xff1f;还是机器人&#xff1f; 然后推送的东西也不知道我想要的&#xff0c;难道年龄到了&#xff0c;就活该天…

在 Windows 11上安装 .NET Framework 3.5

在 Windows 11上安装 .NET Framework 3.5 在控制面板中启用 .NET Framework 3.5 在安装某些软件时&#xff0c;会弹出以下界面&#xff0c;显示需要安装【 .NET Framework 3.5】。 安装微软官方建议进行安装&#xff1a; Microsoft-https://learn.microsoft.com/zh-cn/dotnet…

性能测试的方法有哪些?

性能测试是软件开发过程中非常重要的一环&#xff0c;它能够评估系统的性能以及稳定性。在进行性能测试之前&#xff0c;需要制定一系列的测试方法和策略&#xff0c;以确保测试的准确性和有效性。下面是一篇详细且规范的文章&#xff0c;介绍了性能测试的方法。 第一部分&…

Python中排序算法之冒泡排序

排序算法是将给定的数列中的数进行升序&#xff08;从小到大&#xff09;或者降序&#xff08;从大到小&#xff09;排列。冒泡排序是排序算法的一种。 1 冒泡排序的原理 1.1 基本思想 冒泡排序是将数据中较大或者较小的数据依次向右推移的一种排序技术。它的基本思想是比较…

js实现3d拖拽环绕旋转

js实现拖动节点围绕圆心转动 1.使用transform属性&#xff0c;将圆环放倒展示为椭圆 圆环上有不同的色彩&#xff0c;在转动的同时&#xff0c;需要让圆环也转动&#xff0c;所以圆环不能是椭圆&#xff0c;而是圆形&#xff0c;这样在转动的时候&#xff0c;改变rotate&…

Cypress第二次安装遇到的问题

问题一&#xff1a;吐血&#xff0c;谁会想到node.js的官网访问不了呢&#xff01; 中文网站&#xff1a;http://url.nodejs.cn/download/ 官网&#xff1a;https://nodejs.org/zh-cn nodejs安装的两种方法(官网、NVM安装-node版本切换)不知道这种方式是否可行&#xff0c;还…

Android UI绘制原理:UI的绘制流程是怎么样呢?为什么子线程不能刷新UI呢?讲解大体的流程是怎么样的

目录&#xff1a; 为什么子线程不能刷新UI呢&#xff0c;原因是什么&#xff1f;UI绘制原理 2.1 创建Activity 实例和view的树型结构 2.2 管理绘制的类&#xff1a;ViewRootImpl 2.3 是如何触发刷新View的&#xff1f; 2.4 View的绘制流程&#xff1a;测量(Measure) 2.5 View的…

1998-2023年上市公司研发投入数据

1998-2023年上市公司研发投入数据 1、时间&#xff1a;1998-2023年 2、来源&#xff1a;上市公司年报 3、指标&#xff1a;证券代码、统计截止日期、数据来源、报表类型、研发人员数量&#xff08;人&#xff09;、研发人员数量占比(%)、研发投入金额&#xff08;元&#xf…

MyBatis一级缓存和二级缓存以及 mybatis架构

缓存 数据缓存&#xff0c;让数据离我们执行的程序更近一点&#xff0c;让程序能够快速的获取到数据 缓存的作用就是减轻数据库的压力&#xff0c;提高查询性能。缓存实现的原理是从数据库中查询出来的对象在使用完后不要销毁&#xff0c;而是存储在内内&#xff08;缓存&…

亚马逊无货源店群模式是什么?2024年还能做吗?

相信众多的电商卖家&#xff0c;对店群模式并不陌生。近年来国内电商的店群模式竞争激烈&#xff0c;近乎饱和。那么&#xff0c;在国际知名的跨境电商平台亚马逊上&#xff0c;店群模式又是如何运作呢&#xff1f;到了2024年&#xff0c;亚马逊的店群模式还值得做吗&#xff1…

EAST文本检测

原文:EAST文本检测 - 知乎 (zhihu.com) 一、文本检测 论文: https://arxiv.org/pdf/1704.03155.pdf​arxiv.org/pdf/1704.03155.pdf 一般的文本检测模型会分多个阶段(multi-stage)进行,在训练时需要把文本检测切割成多个阶段(stage)来进行学习,这种把完整文本行先分…

表达式求值问题的实现

这是C算法基础-数据结构专栏的第二十二篇文章&#xff0c;专栏详情请见此处。 引入 相信大家都会做如1(23)*4/5-6这样的算式&#xff0c;而我们今天要学习让计算机通过表达式求它的值&#xff0c;这就是表达式求值问题。 下面我们就来讲表达式求值问题的实现。 定义 表达式求值…

mysql的聚簇索引、非聚簇索引、回表

1.聚簇索引和非聚簇索引 聚簇索引&#xff08;聚集索引&#xff09;&#xff1a;数据和索引放在一起&#xff0c;B树的叶子节点存放了整行数据&#xff0c;有且只有一个。 【主键索引和唯一索引&#xff0c;主键唯一&#xff0c;存放的是主键对应的整行数据】非聚簇索引&#…

[CR]厚云填补_Diffusion Enhancement for CR

Diffusion Enhancement for Cloud Removal in Ultra-Resolution Remote Sensing Imagery Abstract 云层的存在严重影响了光学遥感图像的质量和有效性。然而&#xff0c;现有的基于深度学习(DL)的云移除(CR)技术&#xff0c;通常以保真度驱动的损失作为约束&#xff0c;例如L1或…

USB3.2 摘录(11)

系列文章目录 USB3.2 摘录&#xff08;一&#xff09; USB3.2 摘录&#xff08;二&#xff09; USB3.2 摘录&#xff08;三&#xff09; USB3.2 摘录&#xff08;四&#xff09; USB3.2 摘录&#xff08;五&#xff09; USB3.2 摘录&#xff08;六&#xff09; USB3.2 摘录&…

OpenAI神秘“草莓”项目 计划最早今年秋季推出

据科技媒体The Information报道&#xff0c;OpenAI神秘“草莓”项目&#xff0c;计划最早今年秋季推出&#xff01;上个月&#xff0c;OpenAI的内部团队被曝出正开发的“草莓”&#xff08;Strawberry&#xff09;项目&#xff0c;目的是增强OpenAI的模型的推理能力&#xff0c…

大模型从入门到精通—— LLM 应用评估(一)

如何评估 LLM 应用 1. 简介 在使用大型语言模型&#xff08;LLM&#xff09;构建应用程序时&#xff0c;评估的思路往往与传统的 AI 开发有所不同。传统 AI 的评估可能依赖于大规模的标注数据集和精细的性能指标&#xff0c;而 LLM 的开发则更注重迭代验证&#xff0c;并在开发…

python从入门到精通:异常操作、模块操作及包操作

目录 1、异常概念 2、异常的捕获方法 3、异常的传递 4、python模块 4.1、模块的导入 4.2、自定义模块 5、python包 5.1、自定义python包 5.2、安装第三方包 1、异常概念 当检测到一个错误时&#xff0c;python解释器会无法执行&#xff0c;反而出现一些错误的提示&a…

视频中间件:大华视频设备接入管理应用

前言 上篇博文介绍了视频中间件&#xff1a;海康视频设备的接入管理&#xff1f;&#xff0c;今天给大家带来大华视频设备的接入管理&#xff0c;视频中间件平台支持大华Sdk、大华主动注册、Onvif、Rtsp、Gb28181等方式对大华视频设备的接入管理。同时视频中间件可支持协议互转…

离子交换技术在含银废水处理中的创新应用

随着科技的不断进步&#xff0c;金属制品在各行各业中扮演着越来越重要的角色。其中&#xff0c;镀银工艺作为一种提高金属制品性能的重要手段&#xff0c;其环境影响也日益受到关注。镀银过程中产生的含银废水含有多种有害物质&#xff0c;对环境构成潜在风险。因此&#xff0…