9

在 Spring 3 SpEL 中,#this并被#root引入。

变量#root 始终被定义并引用根上下文对象。尽管 #this 可能会随着表达式的组件的计算而变化,但 #root 始终指的是根。

我已经浏览了文档,但我仍然不明白是什么#root意思(没有例子)。有人可以给我一个例子吗?

4

2 回答 2

12

假设我们有以下代码片段,它用几个素数填充列表并将其定义为 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]。它是如何工作的 ?

  • #primesprimes列表。
  • 选择运算符匹配列表中不为空且与括号中给出的条件匹配的?[]每个对象。在我们的示例中,标准是。指当前的评估对象,在我们的示例中,它是当前正在检查的列表中的对象是否为非空和 > 10iprimes#this > 10#this

评估结果将是一个列表,其中包含:

[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);

这将为someObjectSpEL 上下文创建一个根对象变量。

一个带有#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什么?

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

更多信息:

于 2013-10-23T19:57:49.070 回答
3

在诸如集合投影之类的过程中,#this对象相对于表达式的一部分会发生变化,但#root对象不会。

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

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

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

如果您有一个更有趣对象的列表,例如Collection Selection 文档示例

Members.?[Nationality == 'Serbian']

那个“国籍”是相对于#this成员对象的。如果您想与根上下文变量而不是字符串文字进行比较,则需要执行以下操作:

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

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

于 2017-11-22T19:33:01.660 回答