4.3语言引用

本节介绍Spring表达式语言的工作原理。它包括以下主题:

  • 文字表达式

  • 属性、数组、列表、映射和索引器

  • 内联 List

  • 内联 Map

  • Array

  • 方法

  • Operators

  • 类型

  • Constructors

  • 变量

  • 功能

  • bean引用

  • 三元运算符(if-then-else)

  • elvis

  • Safe Navigation Operator

4.3.1 文字表达式

支持的文本表达式类型包括字符串、数值(int、real、hex)、布尔值和null。字符串由单引号分隔。要将单引号本身放入字符串中,请使用两个单引号字符。

下面的列表显示了文本的简单用法。通常,它们不会像这样单独使用,而是作为更复杂表达式的一部分-例如,在逻辑比较运算符的一侧使用文本。

数字支持使用负号、指数记数法和小数点。默认情况下,使用double.parseDouble()解析实数。

4.3.2 Properties, Arrays, Lists, Maps, and Indexers

使用属性引用导航很容易。为此,请使用句点指示嵌套的属性值。

inventor类的实例pupin和tesla使用示例部分中使用的类中列出的数据填充。为了“向下”导航并获得特斯拉的出生年份和小狗出生城市,我们使用以下表达式:

属性名称的第一个字母允许不区分大小写。数组和列表的内容是使用方括号表示法获得的,如下例所示:

映射的内容是通过在括号内指定文本键值获得的。在下面的示例中,由于Officers map的键是字符串,因此我们可以指定字符串文本:

4.3.3 内联List

你可以使用符号直接在表达式中表示列表。

{}本身就是一个空列表。出于性能原因,如果列表本身完全由固定的文本组成,则会创建一个常量列表来表示表达式(而不是在每个计算上构建一个新列表)。

4.3.4 内联Maps

你还可以使用key:value表示法在表达式中直接表示映射。以下示例显示了如何执行此操作:

{:}代表着空map。出于性能原因,如果映射本身由固定的文本或其他嵌套常量结构(列表或映射)组成,则会创建一个常量映射来表示表达式(而不是在每个计算上构建一个新的映射)。Map的key的引号是可选的。上面的示例不使用带引号的键。

4.3.5 Array构造函数

可以使用熟悉的Java语法构建数组,可以选择的提供初始化器,以便在构建时填充数组。以下示例显示了如何执行此操作:

构造多维数组时,当前无法提供初始值设定项。

4.3.6 方法

可以通过使用典型的Java编程语法来调用方法。还可以对文本调用方法。还支持变量参数。以下示例演示如何调用方法:

4.3.7 Operators

spEL支持下面的运算符:

  • 关系运算符

  • 逻辑运算符

  • 算数运算符

  • 赋值运算符

关系运算符

使用标准运算符表示法支持关系运算符(等于、不等于、小于、小于或等于、大于和大于或等于)。以下列表显示了一些运算符示例:

与null的大于或小于比较遵循一个简单规则:null被视为无(不是零)。因此,任何其他值始终大于null值(x>null始终为真),任何其他值始终小于零(x < null 始终为假)。

如果你更喜欢数值比较,请避免基于数字的null比较,而是与零比较(例如,x>0或x<0)。

除了标准的关系运算符之外,spel还支持instanceof和基于正则表达式的matches运算符。下面的列表显示了这两种方法的示例:

请小心处理基础类型,因为它们会立即装箱到包装类型,因此1 instanceof t(int)的计算结果为false,而1 instanceof t(Integer)的计算结果为true,如预期的那样。

每个符号运算符也可以指定为纯字母等价物。这样可以避免使用的符号对嵌入表达式的文档类型(如XML文档)具有特殊意义的问题。文本等价物为:

所有的文本操作符都不区分大小写。

逻辑操作符

SpEL支持下面的逻辑操作符:

  • and

  • or

  • not

下面的例子展示了如何使用logical操作符:

数学运算符

可以对数字和字符串使用加法运算符。只能对数字使用减法、乘法和除法运算符。你还可以使用模量(%)和指数幂(^)运算符。执行标准运算符优先级。以下示例显示了使用中的数学运算符:

赋值操作

要设置属性,请使用赋值运算符(=)。这通常在对setValue的调用中完成,但也可以在对getValue的调用中完成。下面的列表显示了使用赋值运算符的两种方法:

4.3.8 类型

你可以使用特殊的T运算符来指定java.lang.class(类型)的实例。静态方法也可以使用此运算符调用。StandardEvaluationContext使用TypeLocator来查找类型,StandardTypeLocator(可以替换)是在理解java.lang包的基础上构建的。这意味着T()对java.lang中类型的引用不需要完全限定,但所有其他类型引用都必须是限定的。下面的示例演示如何使用T运算符:

4.3.9 构造器

可以使用new运算符调用构造函数。除了基元类型(int、float等)和字符串之外,其他类型都应该使用完全限定的类名。下面的示例演示如何使用新的运算符来调用构造函数:

4.3.10 变量

可以使用#variableName语法引用表达式中的变量。变量是通过在EvaluationContext实现上使用setVariable方法设置的。以下示例显示如何使用变量:

#this和#root

#this始终是定义的,并引用当前的评估对象(不合格的引用将根据该对象进行解析)。#root变量总是被定义并引用根上下文对象。尽管#this可能会随着表达式的组件的计算而变化,但是#root始终引用根。以下示例说明如何使用#this和#root变量:

4.3.11 函数

你可以通过注册可以在表达式字符串中调用的用户定义函数来扩展spel。该函数通过EvaluationContext注册。以下示例显示如何注册用户定义函数:

例如,考虑以下反转字符串的实用程序方法:

然后你可以注册并使用前面的方法,如下示例所示:

4.3.12 Bean引用

如果已使用bean resolver配置了评估上下文,则可以使用@符号从表达式中查找bean。以下示例显示了如何执行此操作:

要访问工厂bean本身,你应该在bean名称前面加上&符号。以下示例显示了如何执行此操作:

4.3.13 If-Then-Else

可以使用三元运算符在表达式中执行if-then-else条件逻辑。下面的列表显示了一个最小的示例:

在这种情况下,布尔值false会返回字符串值“falseExp”。一个更现实的例子如下:

有关三元运算符的更短语法,请参阅ELVIS运算符。

4.3.14 Elvis

ELVIS运算符是三元运算符语法的缩写,在groovy语言中使用。对于三元运算符语法,通常必须重复变量两次,如下示例所示:

相反,你可以使用Elvis操作符(以Elvis的发型命名)。下面的示例演示如何使用Elvis运算符:

下面的列表显示了一个更复杂的示例:

可以使用ELVIS运算符在表达式中应用默认值。下面的示例演示如何在@value表达式中使用elvis运算符:

@Value("#{systemProperties['pop3.port'] ?: 25}")

如果定义了系统属性pop3.port,则会注入该属性,否则会注入25。

4.3.15 Safe Navigation 运算符

Safe Navigation操作符用于避免nullpointerException,它来自groovy语言。通常,当你引用一个对象时,你可能需要在访问该对象的方法或属性之前验证它不是空的。为了避免这种情况,Safe Navigation操作符返回空值而不是抛出异常。以下示例说明如何使用Safe Navigation:

4.3.16 集合选择

Selection是一种功能强大的表达式语言功能,通过从源集合的条目中进行选择,可以将源集合转换为另一个集合。

Selection使用的语法为.?[selectionExpression]。它过滤集合并返回包含原始元素子集的新集合。例如,selection可以让我们很容易地获得塞尔维亚发明家的列表,如下示例所示:

在list和map上都可以Selection。对于list,将根据每个单独的列表元素评估选择条件。针对map,选择标准针对每个映射条目(Java类型Map.Entry)进行评估。每个map项都有其键和值,可以作为属性访问,以便在选择中使用。

以下表达式返回一个新map,该映射由原始map的那些元素组成,其中输入值小于27:

除了返回所有选定的元素之外,你还能检索第一个或最后一个值。要获取与所选内容匹配的第一个条目,语法为。.^[selectionExpression]。要获取最后一个匹配的选择,语法为.$[SelectionExpression]。

4.3.17 集合投影

Projection允许集合驱动子表达式的计算,结果是一个新集合。投影的语法是.![projectionExpression]。例如,假设我们有一个发明家列表,但是想要他们出生的城市列表。实际上,我们想为发明家列表中的每个条目评估“placeofbirth.city”。下面的示例使用投影进行此操作:

你还可以使用map来驱动投影,在这种情况下,投影表达式针对map中的每个条目(表示为Java Map.Entry)进行评估。跨map投影的结果是一个列表,其中包含对每个map条目的投影表达式的计算。

4.3.18 表达式模板化

表达式模板允许将文本与一个或多个计算块混合。每个评估块都由你可以定义的前缀和后缀字符分隔。常见的选择是使用#{ }作为分隔符,如下示例所示:

字符串的计算方法是将文本“random number is”与计算#{ }分隔符内表达式的结果(在本例中,是调用该random()方法的结果)连接起来。parseExpression()方法的第二个参数的类型为parserContext。ParserContext接口用于影响表达式的解析方式,以支持表达式模板化功能。TemplateParserContext的定义如下:

最后更新于

这有帮助吗?