20200105 Spring official documents (Core 4)

4.Spring Expression Language (SpEL)

Spring expression language (abbreviated SpEL) is a powerful expression language, support query and manipulate an object graph at runtime. Language syntax is similar to Unified EL, but provides additional features, most notably a string method calls and basic templates.

Spring Expression Language was created to provide an expression language that well-supported by the Spring community, the language is available for all versions of the product. It does not bind directly with Spring, can be used independently.

4.1. Evaluation (Evaluation)

The following code describes SpEL API to evaluate the literal string expression Hello World.

ExpressionParser parser = new SpelExpressionParser();
Expression exp = parser.parseExpression("'Hello World'"); 
String message = (String) exp.getValue();

SpEL classes and interfaces that you most likely to use is located in org.springframework.expressionthe package and its subpackages, for example spel.support.

ExpressionParserInterface is responsible for parsing an expression string. In the previous example, the expression character string is represented by a string of single quotes around. ExpressionInterface is responsible for assessing expression string previously defined. Each call parser.parseExpressionand exp.getValuewhen, can lead to two exceptions, ParseExceptionand EvaluationException.

SpEL support a variety of functions, such as call methods, access properties and call the constructor.

SpEL also using standard dot notation (e.g. prop1.prop2.prop3to support nested properties) and the corresponding property value. You can also access public fields.

// 调用方法
Expression exp = parser.parseExpression("'Hello World'.concat('!')"); 
String message = (String) exp.getValue();

// 调用属性
Expression exp = parser.parseExpression("'Hello World'.bytes");
byte[] bytes = (byte[]) exp.getValue();

// 使用点表示法获取文字的长度
Expression exp = parser.parseExpression("'Hello World'.bytes.length"); 
int length = (Integer) exp.getValue();

// 调用String的构造函数,而不是使用字符串文字
Expression exp = parser.parseExpression("new String('hello world').toUpperCase()"); 
String message = exp.getValue(String.class);

Note the use of common public <T> T getValue(Class<T> desiredResultType)methods: . This method does not require the use of the value of the expression is cast to a desired result type. If the value can not be converted to Tthe type of or inability to use the registered type converter to convert it is thrown EvaluationException.

SpEL more common usage is to provide a string expression evaluated for a particular object instance (called the root object). The following example shows how to retrieve the name of the attribute from the class or instance Inventor how to create Boolean condition:

// Create and set a calendar
GregorianCalendar c = new GregorianCalendar();
c.set(1856, 7, 9);

// The constructor arguments are name, birthday, and nationality.
Inventor tesla = new Inventor("Nikola Tesla", c.getTime(), "Serbian");

ExpressionParser parser = new SpelExpressionParser();

Expression exp = parser.parseExpression("name"); // Parse name as an expression
String name = (String) exp.getValue(tesla);
// name == "Nikola Tesla"

exp = parser.parseExpression("name == 'Nikola Tesla'");
boolean result = exp.getValue(tesla, Boolean.class);
// result == true

4.1.1. Understand EvaluationContext

In assessing expression to resolve properties, methods, or types of field and help perform conversion, using EvaluationContextthe interface. Spring provides two implementations.

  • SimpleEvaluationContext: For all SpEL language syntax and does not need to be subject to meaningful expression category restrictions, disclose a subset of SpEL basic language features and configuration options. Examples include, but are not limited to binding expression data and attribute-based filter.
  • StandardEvaluationContext: Open all SpEL language features and configuration options. You can use it to specify the default root object and configure each of the available assessments related strategies.

SimpleEvaluationContextSpEL designed to support only a subset of the language syntax. It does not include references to Java types, constructors, and Bean reference. It also requires that you explicitly choose to support the level of expression of properties and methods. By default, create()the static factory method to enable only read access to the property. You can also get the builder to configure the exact level of support required, and one or more combinations of:

  • Only custom PropertyAccessor(non-reflective)
  • Read-only access data binding properties
  • Reading and writing data binding properties

Type Conversion

By default, SpEL use the conversion service available in Spring core ( org.springframework.core.convert.ConversionService). This conversion service comes with many built-in converter for converting common, but also fully extensible, so that you can add custom conversion between types. In addition, it is the perception of generics. This means that when you use a generic type in an expression, SpEL will try to convert the type of maintenance to the correctness of any object encountered.

Indeed What does this mean? Assuming setValue()assignment to set the Listproperty. This type of property is actually List <Boolean>. SpEL recognize the elements of the list need to be converted to a Boolean value into the list before. The following example shows how to do this:

class Simple {
    public List<Boolean> booleanList = new ArrayList<Boolean>();
}

Simple simple = new Simple();
simple.booleanList.add(true);

EvaluationContext context = SimpleEvaluationContext.forReadOnlyDataBinding().build();

// "false" is passed in here as a String. SpEL and the conversion service
// will recognize that it needs to be a Boolean and convert it accordingly.
parser.parseExpression("booleanList[0]").setValue(context, simple, "false");

// b is false
Boolean b = simple.booleanList.get(0);

4.1.2. Parser configuration

You can use the parser configuration object ( org.springframework.expression.spel.SpelParserConfiguration) SpEL expression parser configuration. Configuration object to control the behavior of certain components of expression. For example, if you index into an array or collection, and the index of the specified element null, you can automatically create the element. When using the expression refers chain consists of properties, which is very useful. If you index into an array or list and specify the index beyond the end of the current size of the array or list, it can automatically grow to accommodate the array or list index. The following example shows how to automatically increase the list:

class Demo {
    public List<String> list;
}

// Turn on:
// - auto null reference initialization
// - auto collection growing
SpelParserConfiguration config = new SpelParserConfiguration(true,true);

ExpressionParser parser = new SpelExpressionParser(config);

Expression expression = parser.parseExpression("list[3]");

Demo demo = new Demo();

Object o = expression.getValue(demo);

// demo.list will now be a real collection of 4 entries
// Each entry is a new empty String

4.1.3. Compile SpEL

Spring Framework 4.1 contains a basic expression compiler. The expression is usually explained, this provides a great dynamic flexibility in the assessment process, but can not provide the best performance. For occasional use an expression, which is good, but when used in conjunction with other components (such as Spring Integration), performance may be very important, and does not require dynamic.

SpEL compiler is designed to meet this need.

Compilation best suited to the type of information when evaluating repeat does not change expression.

Compiler configuration

The compiler does not open by default, but you can open it in one of two different ways. When the usage SpEL embedded in another component, or may be used during use of the system parser configuration property to open it.

The compiler can org.springframework.expression.spel.SpelCompilerModecapture enumeration in three modes of operation it.

  • OFF (Default): Compiler closed.
  • IMMEDIATE: In IMMEDIATE mode, will compile the expression as soon as possible. Usually after the first explanation assessment. If the compiled expression failed (usually due to the type of change, as mentioned above), the expression evaluates the value of the caller will receive an exception.
  • MIXED: In mixed mode, the silent expression with time to switch between modes interpretation and compilation mode. After a certain number of operation explanation, they will be switched to the compiled form, a problem if the compiled form (e.g., as previously described type change), the expression will automatically switch back interpretation forms. Later, it may be used to generate and compile using another form. Basically, the user enters the abnormality mode IMMEDIATE is handled internally.

IMMEDIATE exists mode, because MIXED mode may cause problems with side effects expression. If the compiled expression after the collapse of the partially successful, it may affect the operating system has completed the state. If this happens, the caller may not want to run it again silently in interpreted mode, as part of an expression might run twice.

After the selected mode, SpelParserConfigurationto configure the parser. The following example shows how to do this:

SpelParserConfiguration config = new SpelParserConfiguration(SpelCompilerMode.IMMEDIATE,
    this.getClass().getClassLoader());

SpelExpressionParser parser = new SpelExpressionParser(config);

Expression expr = parser.parseExpression("payload");

MyMessage message = new MyMessage();

Object payload = expr.getValue(message);

When the compile mode, can also specify a class loader (allows passing null). Compiled expressions defined in any sub-class loader provided. It is important to ensure that, if the class loader is specified, it can see all types of expression evaluation process involved. If the class loader is not specified, the default class loader (typically run during expression evaluation thread's context class loader).

The compiler second configuration approach is to embed into SpEL other components, and may not be configured through the configuration object. In these cases, the system can use the attribute. You can set spring.expression.compiler.modethe property to an SpelCompilerModeenumeration value off( , immediate, or mixed)

Compiler limit

Starting Spring Framework 4.1, you have a basic compiler framework. However, this framework does not yet support each compiled expression. The initial focus is the general expression might be used in performance-critical context. Currently do not compile the following types of expressions:

  • Expressions involving assignment
  • Conversion services dependent expression
  • Use custom parsers or accessor expression
  • Using the selected projection or expression (Expressions using selection or projection)

Future type of expression will compile more.

4.2. Bean definition of expression

You can SpEL expressions used in conjunction with XML-based or annotation-based configuration metadata to define BeanDefinitioninstances. In both cases, the syntax for defining expressions are the form #{ <expression string> }.

4.2.1. XML deployment

Expression can be used to set properties or constructor argument values, as shown in the following example:

<bean id="numberGuess" class="org.spring.samples.NumberGuess">
    <property name="randomNumber" value="#{ T(java.lang.Math).random() * 100.0 }"/>

    <!-- other properties -->
</bean>

systemPropertiesVariable is predefined, so you can use it, as shown in the following example in the expression:

<bean id="taxCalculator" class="org.spring.samples.TaxCalculator">
    <property name="defaultLocale" value="#{ systemProperties['user.region'] }"/>

    <!-- other properties -->
</bean>

Please note that in this case, does not have to precede predefined variables #symbols.

You can also reference other bean properties by name as in the following example:

<bean id="numberGuess" class="org.spring.samples.NumberGuess">
    <property name="randomNumber" value="#{ T(java.lang.Math).random() * 100.0 }"/>

    <!-- other properties -->
</bean>

<bean id="shapeGuess" class="org.spring.samples.ShapeGuess">
    <property name="initialShapeSeed" value="#{ numberGuess.randomNumber }"/>

    <!-- other properties -->
</bean>

4.2.2. Comments configuration

To specify a default value, can @Valuecomment on the field, and a method or a constructor parameter.

The following example sets the default value field variable:

public class FieldValueTestBean {

    @Value("#{ systemProperties['user.region'] }")
    private String defaultLocale;

    public void setDefaultLocale(String defaultLocale) {
        this.defaultLocale = defaultLocale;
    }

    public String getDefaultLocale() {
        return this.defaultLocale;
    }
}

The following example shows an example but using an equivalent property setter methods:

public class PropertyValueTestBean {

    private String defaultLocale;

    @Value("#{ systemProperties['user.region'] }")
    public void setDefaultLocale(String defaultLocale) {
        this.defaultLocale = defaultLocale;
    }

    public String getDefaultLocale() {
        return this.defaultLocale;
    }
}

Automatic assembly methods and constructors may be used @Value annotations, as shown in the following example:

public class SimpleMovieLister {

    private MovieFinder movieFinder;
    private String defaultLocale;

    @Autowired
    public void configure(MovieFinder movieFinder,
            @Value("#{ systemProperties['user.region'] }") String defaultLocale) {
        this.movieFinder = movieFinder;
        this.defaultLocale = defaultLocale;
    }

    // ...
}
public class MovieRecommender {

    private String defaultLocale;

    private CustomerPreferenceDao customerPreferenceDao;

    public MovieRecommender(CustomerPreferenceDao customerPreferenceDao,
            @Value("#{systemProperties['user.country']}") String defaultLocale) {
        this.customerPreferenceDao = customerPreferenceDao;
        this.defaultLocale = defaultLocale;
    }

    // ...
}

4.3. Language Reference

4.3.1. Literal expression

Type supports text expression to a string, numeric (int, real numbers, hexadecimal), boolean, and null. String by a single quotation marks. To single quote itself in a string, use two single quote characters.

The following list shows the simple use of text. Typically, they are not as such be used in isolation, but as part of a more complex use of regular expressions - e.g., the use of text side logical comparison operator.

ExpressionParser parser = new SpelExpressionParser();

// evals to "Hello World"
String helloWorld = (String) parser.parseExpression("'Hello World'").getValue();

double avogadrosNumber = (Double) parser.parseExpression("6.0221415E+23").getValue();

// evals to 2147483647
int maxValue = (Integer) parser.parseExpression("0x7FFFFFFF").getValue();

boolean trueValue = (Boolean) parser.parseExpression("true").getValue();

Object nullValue = parser.parseExpression("null").getValue();

Digital support using the minus sign, exponent sign and decimal point. By default, the use of Double.parseDouble()analytic real number.

4.3.2. Properties, Arrays, Lists, Maps, 和 Indexers

The first letter of the name of the property to allow case-insensitive. And a list of contents of the array by using square brackets indicate obtain law.

Map content can be obtained by specifying key words in square brackets.

parser.parseExpression("Officers['advisors'][0].PlaceOfBirth.Country").setValue(societyContext, "Croatia");

4.3.3. Inline list (Inline Lists)

You can use the {}expression list directly in the expression symbol.

// evaluates to a Java list containing the four numbers
List numbers = (List) parser.parseExpression("{1,2,3,4}").getValue(context);

List listOfLists = (List) parser.parseExpression("{{'a','b'},{'x','y'}}").getValue(context);

{}Itself implies an empty list. For performance reasons, if the list itself is composed entirely of fixed text, it will create a list of constants to represent the expression (have established a new list of time rather than at each evaluation).

4.3.4. Inline Map

You can also use the {key:value}expression directly in the expression symbol Map. The following example shows how to do this:

// evaluates to a Java map containing the two entries
Map inventorInfo = (Map) parser.parseExpression("{name:'Nikola',dob:'10-July-1856'}").getValue(context);

Map mapOfMaps = (Map) parser.parseExpression("{name:{first:'Nikola',last:'Tesla'},dob:{day:10,month:'July',year:1856}}").getValue(context);

{:}Itself implies a empty Map. For performance reasons, if the Map itself consists of fixed text or other nested structure constant (List or Map) composed of a constant Map is created to represent the expression construct a new all time (not in each evaluation the Map). Map key references are optional. The above quoted example of the key is not used.

4.3.5. Array configuration (Array Construction)

You can use the familiar Java syntax to build the array, you can choose to provide an initialization procedure to fill the array at construction time. The following example shows how to do this:

int[] numbers1 = (int[]) parser.parseExpression("new int[4]").getValue(context);

// Array with initializer
int[] numbers2 = (int[]) parser.parseExpression("new int[]{1,2,3}").getValue(context);

// Multi dimensional array
int[][] numbers3 = (int[][]) parser.parseExpression("new int[4][5]").getValue(context);

When constructing multi-dimensional array, it is currently unable to provide initialization procedure.

4.3.6. method

You can use the typical Java programming syntax to invoke the method. You can also invoke methods on the text. Also supports variable parameters. The following example demonstrates how to call the method:

// string literal, evaluates to "bc"
String bc = parser.parseExpression("'abc'.substring(1, 3)").getValue(String.class);

// evaluates to true
boolean isMember = parser.parseExpression("isMember('Mihajlo Pupin')").getValue(
        societyContext, Boolean.class);

4.3.7. Operators

Relational Operators

Using a standard notation operator support relational operators (equal to, not equal to, less than, less than, or equal to, greater than, and greater than or equal to).

// evaluates to true
boolean trueValue = parser.parseExpression("2 == 2").getValue(Boolean.class);

// evaluates to false
boolean falseValue = parser.parseExpression("2 < -5.0").getValue(Boolean.class);

// evaluates to true
boolean trueValue = parser.parseExpression("'black' < 'block'").getValue(Boolean.class);

Of nullgreater than and less than comparative follow a simple rule: null is considered no (not zero). As a result, always greater than any other value null ( X > nullalways true), and any other value not less than zero ( X < nullalways false).

If you prefer a digital comparator, avoid using numbers based on a comparison of air, and the proposed use compared to zero (for example, X > 0or X < 0).

In addition to standard relational operators, SpEL supports instanceofand regular expression-based matchesoperator. The following list shows two examples:

// evaluates to false
boolean falseValue = parser.parseExpression(
        "'xyz' instanceof T(Integer)").getValue(Boolean.class);

// evaluates to true
boolean trueValue = parser.parseExpression(
        "'5.00' matches '^-?\\d+(\\.\\d{2})?$'").getValue(Boolean.class);

//evaluates to false
boolean falseValue = parser.parseExpression(
        "'5.0067' matches '^-?\\d+(\\.\\d{2})?$'").getValue(Boolean.class);

Note primitive types, since they immediately be packaged as a wrapper type, therefore, as expected, a instanceof T(int)calculation result is false, and a calculation result instanceof T (Integer) is true.

Each symbol operator can also specify the letter equivalent pure. The problem (for example, in an XML document) to avoid the use of such symbols for the embedded document type expressions that have special meaning. The text equivalent is:

  • lt(<)
  • gt(>)
  • the (<=)
  • ge(>=)
  • eq(==)
  • not (! =)
  • div(/)
  • mod(%)
  • not(!)

All operators are case-insensitive text.

Logical Operators

SpEL supports the following logical operators:

  • and
  • or
  • not
// evaluates to false
boolean falseValue = parser.parseExpression("true and false").getValue(Boolean.class);

// evaluates to true
String expression = "isMember('Nikola Tesla') and isMember('Mihajlo Pupin')";
boolean trueValue = parser.parseExpression(expression).getValue(societyContext, Boolean.class);

// -- OR --

// evaluates to true
boolean trueValue = parser.parseExpression("true or false").getValue(Boolean.class);

// evaluates to true
String expression = "isMember('Nikola Tesla') or isMember('Albert Einstein')";
boolean trueValue = parser.parseExpression(expression).getValue(societyContext, Boolean.class);

// -- NOT --

// evaluates to false
boolean falseValue = parser.parseExpression("!true").getValue(Boolean.class);

// -- AND and NOT --
String expression = "isMember('Nikola Tesla') and !isMember('Mihajlo Pupin')";
boolean falseValue = parser.parseExpression(expression).getValue(societyContext, Boolean.class);

Mathematical Operators

You can use the addition operator on the numbers and strings. You can only use subtraction, multiplication and division operator for numbers. You can also use the analog to digital ( ) and exponential power ( ^) operator. Standard enforce operator precedence. The following example shows the mathematical operators used are:

// Addition
int two = parser.parseExpression("1 + 1").getValue(Integer.class);  // 2

String testString = parser.parseExpression(
        "'test' + ' ' + 'string'").getValue(String.class);  // 'test string'

// Subtraction
int four = parser.parseExpression("1 - -3").getValue(Integer.class);  // 4

double d = parser.parseExpression("1000.00 - 1e4").getValue(Double.class);  // -9000

// Multiplication
int six = parser.parseExpression("-2 * -3").getValue(Integer.class);  // 6

double twentyFour = parser.parseExpression("2.0 * 3e0 * 4").getValue(Double.class);  // 24.0

// Division
int minusTwo = parser.parseExpression("6 / -3").getValue(Integer.class);  // -2

double one = parser.parseExpression("8.0 / 4e0 / 2").getValue(Double.class);  // 1.0

// Modulus
int three = parser.parseExpression("7 % 4").getValue(Integer.class);  // 3

int one = parser.parseExpression("8 / 5 % 2").getValue(Integer.class);  // 1

// Operator precedence
int minusTwentyOne = parser.parseExpression("1+2-3*8").getValue(Integer.class);  // -21

Assignment Operators

To set a property, using the assignment operator ( =). This is usually to setValuebe completed within call, but you can have the getValuecomplete internal call. The following listing shows the assignment operator using two methods:

Inventor inventor = new Inventor();
EvaluationContext context = SimpleEvaluationContext.forReadWriteDataBinding().build();

parser.parseExpression("Name").setValue(context, inventor, "Aleksandar Seovic");

// alternatively
String aleks = parser.parseExpression(
        "Name = 'Aleksandar Seovic'").getValue(context, inventor, String.class);

4.3.8. Type (Types)

You can use a special Toperator to specify java.lang.Class(type) of Example. Static methods may be invoked through the use of this operator. StandardEvaluationContextUse TypeLocatorsearch type, and StandardTypeLocator (can replace) in understanding java.langconstructed package case. This means that for java.langthe type of T()references does not require a fully qualified, but all other types of references must be fully qualified. The following example demonstrates how to use the operator T:

Class dateClass = parser.parseExpression("T(java.util.Date)").getValue(Class.class);

Class stringClass = parser.parseExpression("T(String)").getValue(Class.class);

boolean trueValue = parser.parseExpression(
        "T(java.math.RoundingMode).CEILING < T(java.math.RoundingMode).FLOOR")
        .getValue(Boolean.class);

4.3.9. Constructor

You can use the newoperator to call the constructor. In addition to the basic types (int, float, etc.) and String, you should use the fully qualified class name.

Inventor einstein = p.parseExpression(
        "new org.spring.samples.spel.inventor.Inventor('Albert Einstein', 'German')")
        .getValue(Inventor.class);

//create new inventor instance within add method of List
p.parseExpression(
        "Members.add(new org.spring.samples.spel.inventor.Inventor(
            'Albert Einstein', 'German'))").getValue(societyContext);

4.3.10. variable

You can use the #variableNamesyntax reference variables in the expression. By the EvaluationContextuse of the implement setVariablesetting method variable. The following example shows how to use variables:

Inventor tesla = new Inventor("Nikola Tesla", "Serbian");

EvaluationContext context = SimpleEvaluationContext.forReadWriteDataBinding().build();
context.setVariable("newName", "Mike Tesla");

parser.parseExpression("Name = #newName").getValue(context, tesla);
System.out.println(tesla.getName())  // "Mike Tesla"

#this variables and #root

Always defined #thisvariables, and references the current assessment of the object (opposition failed to resolve references). Always defined #rootvariables, and references to the root context object. Although #this may vary with the evaluation part of an expression, but #root always reference the root. The following example shows how to use #this and #root variables:

// 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();
EvaluationContext context = SimpleEvaluationContext.forReadOnlyDataAccess();
context.setVariable("primes", primes);

// all prime numbers > 10 from the list (using selection ?{...})
// evaluates to [11, 13, 17]
List<Integer> primesGreaterThanTen = (List<Integer>) parser.parseExpression(
        "#primes.?[#this>10]").getValue(context);

4.3.11. function

User-defined functions can be called in your expression string by registering to extend SpEL. The function by EvaluationContextregistering. The following example shows how to register a user-defined function:

Method method = ...;

EvaluationContext context = SimpleEvaluationContext.forReadOnlyDataBinding().build();
context.setVariable("myFunction", method);

For example, consider the following utility methods for reversing the string:

public abstract class StringUtils {

    public static String reverseString(String input) {
        StringBuilder backwards = new StringBuilder(input.length());
        for (int i = 0; i < input.length(); i++) {
            backwards.append(input.charAt(input.length() - 1 - i));
        }
        return backwards.toString();
    }
}

ExpressionParser parser = new SpelExpressionParser();

EvaluationContext context = SimpleEvaluationContext.forReadOnlyDataBinding().build();
context.setVariable("reverseString",
        StringUtils.class.getDeclaredMethod("reverseString", String.class));

String helloWorldReversed = parser.parseExpression(
        "#reverseString('hello')").getValue(context, String.class);

4.3.12. Bean references

If the bean has been used to assess the context of the parser configuration, you can use the @symbol lookup bean from the expression. The following example shows how to do this:

ExpressionParser parser = new SpelExpressionParser();
StandardEvaluationContext context = new StandardEvaluationContext();
context.setBeanResolver(new MyBeanResolver());

// This will end up calling resolve(context,"something") on MyBeanResolver during evaluation
Object bean = parser.parseExpression("@something").getValue(context);

To access the factory bean itself, should be changed to add a name before the bean &symbol. The following example shows how to do this:

ExpressionParser parser = new SpelExpressionParser();
StandardEvaluationContext context = new StandardEvaluationContext();
context.setBeanResolver(new MyBeanResolver());

// This will end up calling resolve(context,"&foo") on MyBeanResolver during evaluation
Object bean = parser.parseExpression("&foo").getValue(context);

4.3.13. Ternary operator (If-Then-Else)

String falseString = parser.parseExpression(
        "false ? 'trueExp' : 'falseExp'").getValue(String.class);


parser.parseExpression("Name").setValue(societyContext, "IEEE");
societyContext.setVariable("queryName", "Nikola Tesla");

expression = "isMember(#queryName)? #queryName + ' is a member of the ' " +
        "+ Name + ' Society' : #queryName + ' is not a member of the ' + Name + ' Society'";

String queryResultString = parser.parseExpression(expression)
        .getValue(societyContext, String.class);
// queryResultString = "Nikola Tesla is a member of the IEEE Society"

4.3.14. Elvis operator

Elvis is a simplified operator ternary operator syntax and language used in Groovy.

ExpressionParser parser = new SpelExpressionParser();
EvaluationContext context = SimpleEvaluationContext.forReadOnlyDataBinding().build();

Inventor tesla = new Inventor("Nikola Tesla", "Serbian");
String name = parser.parseExpression("Name?:'Elvis Presley'").getValue(context, tesla, String.class);
System.out.println(name);  // Nikola Tesla

tesla.setName(null);
name = parser.parseExpression("Name?:'Elvis Presley'").getValue(context, tesla, String.class);
System.out.println(name);  // Elvis Presley

You can apply the default values in the expressions used in Elvis operator. The following example shows how to @Valueuse the operator Elvis expression:

@Value("#{systemProperties['pop3.port'] ?: 25}")

pop3.portIf defined, the injection system attributes, otherwise it will inject 25.

4.3.15. Operator safety navigation

Navigation operator safety for avoiding NullPointerExceptionit from Groovy language. Usually, when you refer to an object that may require authentication before access to the object method or property if it is null. To avoid this, the security navigation operator returns null instead of raising it. The following example demonstrates how to use the safe navigation operator:

ExpressionParser parser = new SpelExpressionParser();
EvaluationContext context = SimpleEvaluationContext.forReadOnlyDataBinding().build();

Inventor tesla = new Inventor("Nikola Tesla", "Serbian");
tesla.setPlaceOfBirth(new PlaceOfBirth("Smiljan"));

String city = parser.parseExpression("PlaceOfBirth?.City").getValue(context, tesla, String.class);
System.out.println(city);  // Smiljan

tesla.setPlaceOfBirth(null);
city = parser.parseExpression("PlaceOfBirth?.City").getValue(context, tesla, String.class);
System.out.println(city);  // null - does not throw NullPointerException!!!

4.3.16。Collection Selection

Selection is a powerful expression language feature that allows you to select from a source through the collection to convert it to another collection.

Choose to use the .?[selectionExpression]syntax. It was filtered set and returns a new set containing the original subset of elements.

List<Inventor> list = (List<Inventor>) parser.parseExpression(
        "Members.?[Nationality == 'Serbian']").getValue(societyContext);

On the List and Map can be selected. For a list of selection criteria will be evaluated for each individual list elements. For Map, Map for each entry (type of Java objects) to assess the selection criteria Map.Entry. Each Map entry has its keys and values ​​may be used as accessible attributes for selection.

The following expression returns a new Map, the Map by the original map entry value is less than 27 of those elements consisting of:

Map newMap = parser.parseExpression("map.?[value<27]").getValue();

In addition to returning all selected elements, but you can only retrieve the first or last values. To obtain and select the first entry matching syntax .^[selectionExpression]. For the final match selection, syntax .$[selectionExpression].

4.3.17. Collection Projection

Projection may be set so that the driving evaluation of subexpressions, the result is a new set. The syntax is projected .![projectionExpression].

// returns ['Smiljan', 'Idvor' ]
List placesOfBirth = (List)parser.parseExpression("Members.![placeOfBirth.city]");

You can also use the Map to drive projection, in this case, (the Java representation Map.Entry) Each entry in the map projection expressions are evaluated. Cross-Map projection is the result of a List, which contains the evaluation expression for each projection Map entry.

4.3.18. Expression Templates

Expression template allows literal text mixed with one or more evaluation blocks. Prefix and suffix characters are each evaluation block you can define separate. Common choice is #{ }used as a delimiter as shown, in the following example:

String randomPhrase = parser.parseExpression(
        "random number is #{T(java.lang.Math).random()}",
        new TemplateParserContext()).getValue(String.class);

// evaluates to "random number is 0.7038186818312008"

The text in the text by 'random number is' and the counter #{ }result (in this example, calls to expression in the delimiters evaluated random()to evaluate the results of the method of the string). parseExpression()The second parameter is the method ParserContexttype. ParserContext interface is used to affect the expression of analytical methods to support the expression templates. TemplateParserContext is defined as follows:

public class TemplateParserContext implements ParserContext {

    public String getExpressionPrefix() {
        return "#{";
    }

    public String getExpressionSuffix() {
        return "}";
    }

    public boolean isTemplate() {
        return true;
    }
}

Guess you like

Origin www.cnblogs.com/huangwenjie/p/12151548.html