Spel中的#root和#this

时间:2013-10-23 19:08:27

标签: java spring spring-el

在Spring 3 SpEL中,引入了#this#root

  

始终定义变量#root并引用根上下文   宾语。虽然#this可能因表达式的组成部分而异   评估,#root总是指根。

我已经阅读了文档,但我仍然不明白#root的含义(没有例子)。有人可以举个例子吗?

2 个答案:

答案 0 :(得分:8)

假设我们有以下代码片段,它用几个素数填充列表并将其定义为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);

现在,如果我们想要缩小列表并获得所有&gt;的素数。 10,我们可以使用?[]选择运算符。声明就是这个:

Expression expression = parser.parseExpression("#primes.?[#this>10]");
List<Integer> primesGreaterThanTen = (List<Integer>) expression.getValue(ctx);

如您所见,要评估的表达式为#primes.?[#this > 10]。它是如何工作的?

  • #primes指的是primes列表。
  • ?[]选择运算符会匹配i列表中不为空且符合括号中给出的条件的每个对象primes。在我们的示例中,标准为#this > 10#this指的是当前评估对象,在我们的示例中,该对象将是列表中的对象,此时正在检查该对象是否为空且&gt; 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的力量是什么?

通过单个根对象,您可以为表达式公开全面的自定义环境,例如自定义实用程序方法和/或变量

更多信息:

答案 1 :(得分:1)

#this对象在类似集合投影的过程中相对于表达式的一部分发生了变化,但#root对象并没有。

因此,如果在您的上下文中有两个变量:数字列表myNumbers和单个数字maxNumber,您可以使用SpEL表达式在该列表上创建投影,如:

myNumbers.?[#this lt #root.maxNumber]

在投影表达式(方括号内)中,#this对象是集合中要检查它是否通过过滤器的项目,而#root对象仍然是全球背景下的变量。

如果您有一个更有趣的对象列表,例如Collection Selection documentation example

Members.?[Nationality == 'Serbian']

那&#34;国籍&#34;是相对于成员对象#this。如果要比较根上下文变量而不是字符串文字,则需要执行以下操作:

Members.?[Nationality == #root.searchedForNationality]

如果您刚刚尝试[Nationality == searchedForNationality],那么它将无法正常工作,因为searchedForNationality不是成员对象的一部分,而是根对象上的变量。您需要使用#root来限定它,因为默认情况下,非限定引用是相对于#this对象的。