在Spring 3 SpEL中,引入了#this
和#root
。
变量 #root 始终定义并引用根上下文 对象。尽管 #this 可能会因表达式的组成部分而异 评估时,#root 始终指根。
我已经浏览了文档,但我仍然不明白#root
是什么意思(没有示例)。有人可以给我举个例子吗?
假设我们有以下代码片段,它用几个素数填充列表,并将其定义为 SpEL 上下文中的变量:
// create an array of integers
List<Integer> primes = new ArrayList<Integer>();
primes.addAll(Arrays.asList(2,3,5,7,11,13,17));
// create parser and set variable 'primes' as the array of integers
ExpressionParser parser = new SpelExpressionParser();
StandardEvaluationContext ctx = new StandardEvaluationContext();
ctx.setVariable("primes", primes);
现在,如果我们想缩小列表范围并获取所有> 10 的质数,我们可以使用 ?[]
选择运算符。声明将是这样的:
Expression expression = parser.parseExpression("#primes.?[#this>10]");
List<Integer> primesGreaterThanTen = (List<Integer>) expression.getValue(ctx);
如您所见,要计算的表达式是 #primes.?[#this > 10]
。它是如何工作的?
-
#primes
是指primes
列表。 ?[]
选择运算符匹配primes
列表中i
的每个对象,这些对象不为 null,并且与括号中给出的条件匹配。在我们的示例中,条件为#this > 10
。#this
是指当前评估对象,在我们的示例中,该对象将是当前正在检查的非空和> 10 的列表中的对象。
评估结果将是一个列表,其中包含:
[11, 13, 17]
SpEL 上下文可以具有#root
变量。让我们有这个简单的类:
public class SomeCustomObject {
public int stringLength(String input) {
if (input == null) return 0;
return input.length();
}
}
并将我们的SomeCustomObject
实例定义为#root
变量。
SomeCustomObject someObject = new SomeCustomObject();
context.setRootObject(someObject);
这会将someObject
变量创建为 SpEL 上下文的根对象。
一个包含 #root
变量的简单示例。
String name = "kocko";
ctx.setVariable("name", kocko);
String statement = "#root.stringLength(#kocko) == 5";
Expression expression = parser.parseExpression(statement);
boolean result = expression.getValue(context, Boolean.class);
result
变量将被计算为 true
。
#root
的力量是什么?
通过单个根对象,您可以向表达式公开全面的自定义环境,例如自定义实用程序方法和/或变量。
更多信息:
- SpEL 表达参考指南
在集合投影等操作期间,#this
对象相对于表达式的一部分会发生变化,但#root
对象不会。
因此,如果您的上下文中有两个变量:myNumbers
数字列表和单个数字maxNumber
,您可以使用 SpEL 表达式在该列表上创建一个投影,如下所示:
myNumbers.?[#this lt #root.maxNumber]
在投影表达式(方括号内)中,#this
对象是集合中正在检查它是否通过筛选器的项,而#root
对象仍然是全局上下文中的变量。
如果您有更有趣的对象的列表,如"集合选择"文档示例中所示:
Members.?[Nationality == 'Serbian']
"国籍"是相对于成员对象#this
的。如果要与根上下文变量而不是字符串文本进行比较,则需要执行以下操作:
Members.?[Nationality == #root.searchedForNationality]
如果您刚刚尝试[Nationality == searchedForNationality]
它不起作用searchedForNationality
因为它不是成员对象的一部分,而是根对象上的变量。您需要使用 #root
来限定它,因为默认情况下非限定引用是相对于#this
对象的