#root and # this in SpEL

Spring introduced 3 SpELs, #this and #root .

The variable #root is always defined and refers to the root context of the object. Although # this can vary as the components of the expression are evaluated, #root always refers to the root.

I looked through the documentation, but I still don't understand what #root means (no example). Can someone please give me an example?

+6
source share
2 answers

Let's say we have the following code fragment that populates the list with a few primes and defines it as a variable in the SpEL context:

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

Now, if we want to narrow the list and get all the primes that are> 10, can we use the selection operator ?[] . The statement will be as follows:

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

As you can see, the expression to be evaluated is #primes.?[#this > 10] . How it works?

  • #primes belongs to the primes list.
  • The selection operator ?[] Corresponds to each object i in the primes list, which is not null and meets the criteria indicated in brackets. In our example, the criteria #this > 10 . #this refers to the current evaluation object, which in our example will be the object from the list that is currently being checked for non-null and> 10.

The result of the evaluation will be a list containing:

 [11, 13, 17] 

The SpEL context may have the #root variable. Let this simple class:

 public class SomeCustomObject { public int stringLength(String input) { if (input == null) return 0; return input.length(); } } 

and define an instance of our SomeCustomObject as the #root variable.

 SomeCustomObject someObject = new SomeCustomObject(); context.setRootObject(someObject); 

This will create the variable someObject root object for the SpEL context.

A simple example with the #root variable.

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

The result variable will evaluate to true .

What is the power of #root ?

Through a single root object, you can expose your expressions to a comprehensive custom environment, such as custom methods and / or variables .

Additional Information:

+7
source

The #this object changes relative to part of the expression during something like a projection of a collection, but the #root object #root not.

So, if in your context you have two variables: a list of numbers myNumbers and one number maxNumber , you can create a projection in this list with a SpEL expression, for example:

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

In a projection expression (inside square brackets), the #this object is the element in the collection that is checked to see if it passes the filter, and the #root object is still variables in the global context.

If you have a list of more interesting objects, for example, in the Example documentation for choosing a collection :

 Members.?[Nationality == 'Serbian'] 

That "Nationality" refers to #this , a member object. If you want to compare with the root context variable instead of a string literal, you will need:

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

If you just tried [Nationality == searchedForNationality] , this would not work, because searchedForNationality not part of a member object, but a variable in the root object. You have to use #root to qualify it, because by default unqualified links refer to the #this object.

+1
source

Source: https://habr.com/ru/post/956587/


All Articles