概念:MVEL 基础知识
语法
MVEL 是一种表达式语言,适用于基于 Java 的应用程序。MVEL 的语法类似于 Java,但增加了一些内容,这使得它在内容匹配方面更高效。
注意:
- MVEL 使用 Java 命名空间和类,但它本身不能声明两者。
- 与 Java 不同,MVEL 是动态类型的语言,并且类型是可选的。
- MVEL 表达式可以是单个语句,也可以是多行脚本。对于多行脚本,请使用分号分隔各语句。
- MVEL 根据“最后一个值转出”原则运行。它支持return关键字,但通常不需要它。
- MVEL 支持运算符优先级规则,并使用括号来控制执行顺序。
- 您可以用单引号或双引号将 MVEL 字符串文本括起来。
- 在 MVEL 中,分号是保留字符。不能在表达式中使用。用途(char) 59改为。示例:props['string']='a;b'引发错误。此代码不会:props['string']= (char) 59 props['string_new']='a'props['string']'b'
MVEL 表达式可包括:
- 布尔值表达式
- 方法调用
- 属性表达式
- 变量指定
以下是简单的 MVEL 属性表达式示例:
context.errorMessage
它会提取属性
errorMessage
从变量或上下文对象 context
。MVEL 支持所有常用的 Java 比较运算符、数学运算符和逻辑运算符。下表汇总了其他重要的 MVEL 运算符:
运算符 | 描述 | 示例 |
|---|---|---|
new
| 实例化一个对象。 | new String("foo")
|
with
| 对单个对象实例执行多项操作。 | with (value) { name = 'Foo', age = 50, sex = Sex.MALE }
|
assert
| 对某个值是否为 true 进行断言,否则失败,并返回 AssertionError。 | assert foo != null
|
contains
| 确定左侧的值是否包含右侧的值。 | var contains "Foo"
|
is 或 instance of
| 确定左侧的值是否为右侧类的成员。 | var instanceof String
|
strsim
| 比较字符串,并返回相似度(以百分比表示)。 | "foobol" strsim "foobar"
|
soundslike
| 在 2 个字符串之间执行soundex 比较。 | "foobar" soundslike "fubar"
|
&
| 执行“按位与”运算。 | foo & 5
|
|
| 执行“按位或”运算。 | foo | 5
|
^
| 执行按位异或运算。 | foo ^ 5
|
+
| 用于连接 2 个字符串的重载运算符。 | "foo" + "bar"
|
#
| 将 2 个文本连接为字符串。 | 8 # 9
|
in
| 检查集合内的对象。 | (foo in list)
|
=
| 为变量指定值。 | var = "foobar"
|
值测试
在 Java 中,运算符
==
检查引用是否指向同一个对象。但是,在 MVEL 中,比较运算符 ==
检查值是否相等。MVEL 表达式 foo == 'bar'
与 Java 的等效项 foo.equals("bar")
。MVEL 布尔值表达式的示例:
user.name == 'John Smith'
它会返回
true
如果 name
变量或上下文对象的属性 user
是 John Smith。MVEL 采用类型强制。如果您比较 2 个不同类型的值,MVEL 会尝试将右侧值强制转换为左侧的类型。如果无法执行此操作,则会尝试将左侧值强制转换为右侧的类型。示例:
"123" == 123;
此表达式将返回
true
因为 MVEL 在执行比较之前会将右侧的值强制转换为字符串。列表、映射和数组
将 MVEL 列表括在方括号中。使用逗号分隔各个条目。示例:
["Paris", "London", "Berlin"]
将 MVEL 映射用方括号括起来。用冒号分隔键和值。示例:
["Foo" : "Bar", "Bar" : "Foo"]
将 MVEL 数组括在大括号内。使用逗号分隔各个条目。示例:
{"Bill", "Bob", "Ben"}
属性导航
MVEL 为访问属性、静态字段、列表、映射和数组提供了单一、统一的语法。
在 Java 中,您可以使用以下语句从对象访问属性:
context.getException().getCause()
在 MVEL 中,您可以使用以下表达式访问同一属性:
context.exception.cause
以相同的方式访问列表和数组。示例:
parts[2]
您可以像访问数组一样访问映射,但可以将任何对象作为索引值进行传递。示例:
props["foobar"]
如果映射使用字符串作为键,您可以将映射本身视为虚拟对象。示例:
props.foobar
出于索引目的,MVEL 将字符串视为数组。
此示例将返回
B
:foo = "Berlin"; foo[0];
指定
您可以在 MVEL 表达式中指定变量,以在表达式中使用或在运行时提取。
MVEL 是一种动态类型的语言,因此您在声明新变量时不需要指定类型,但您可以指定。
以下两个示例在 MVEL 中都有效:
str = "Some string"; String str = "Some string";
为类型化变量指定值时,MVEL 会尝试执行自动类型转换。示例:
String num = 1;
您可以将动态类型化变量的值转换为另一种类型。示例:
String num = 1;
版块:键入和强制
MVEL 使用动态类型,并提供了可选的静态类型。原生 Java 对象为静态类型。为与这些对象进行交互,MVEL 有时必须执行强制类型转换,这可能会对性能产生影响。
MVEL 会自动将类型强制转换为最适合当前值的类型。这意味着您在处理数字时必须小心。浮点运算中可能会出现错误,因为 MVEL 会自动放弃无限精度类型转换。
java.math.BigDecimal
至 java.lang.Double
与 java.lang.Long
。当存储值的类型不是您预期的类型时,这可能会导致问题。通常,您应避免对 MVEL 中的财务值执行非整数算术运算。使用 MVEL 的强制类型转换意味着,您可以在不调整输入的情况下调用 Java 方法。解释器或编译器会分析您要传递给方法的类型,并确定所需的强制类型转换。
如果发生数组类型冲突,MVEL 会尝试将整个数组强制转换为所需输入类型。
如果所赋的值可以强制转换,MVEL 会对静态类型变量执行任何必要的强制转换。如果不可以,则会发生异常。