【问题标题】:#root and #this in SpELSpEL 中的 #root 和 #this
【发布时间】:2013-10-23 19:08:27
【问题描述】:

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

变量#root 总是被定义并引用根上下文 目的。虽然 #this 可能会随着表达式的组成部分而变化 评估后,#root 总是指根。

我已经浏览了文档,但我仍然不明白#root 的含义(没有示例)。谁能给我一个例子?

【问题讨论】:

    标签: java spring spring-el


    【解决方案1】:

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

    • #primes 指的是primes 列表。
    • ?[] 选择运算符匹配primes 列表中不为空 且符合括号中给出的条件的每个对象i。在我们的示例中,条件为#this &gt; 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 的威力是什么?

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

    更多信息:

    【讨论】:

      【解决方案2】:

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

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

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

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

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

      Members.?[Nationality == 'Serbian']
      

      “国籍”与成员对象#this 相关。如果您想与根上下文变量而不是字符串文字进行比较,您需要这样做:

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

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

      【讨论】:

        猜你喜欢
        • 2016-07-19
        • 2021-01-10
        • 2019-10-07
        • 1970-01-01
        • 2020-12-16
        • 2011-04-07
        • 1970-01-01
        • 1970-01-01
        • 2013-08-10
        相关资源
        最近更新 更多