Minor documentation refinements (backported from 5.1.x)
This commit is contained in:
parent
4b999cfe95
commit
c096dc45e7
|
|
@ -1,4 +1,4 @@
|
|||
/**
|
||||
* Generic support for SImple Messaging Protocols including protocols such as STOMP.
|
||||
* Generic support for Simple Messaging Protocols including protocols such as STOMP.
|
||||
*/
|
||||
package org.springframework.messaging.simp;
|
||||
|
|
|
|||
|
|
@ -7,17 +7,17 @@
|
|||
[[expressions-intro]]
|
||||
== Introduction
|
||||
|
||||
The Spring Expression Language (SpEL for short) is a powerful expression language that
|
||||
The Spring Expression Language (_SpEL_ for short) is a powerful expression language that
|
||||
supports querying and manipulating an object graph at runtime. The language syntax is
|
||||
similar to Unified EL but offers additional features, most notably method invocation and
|
||||
basic string templating functionality.
|
||||
|
||||
While there are several other Java expression languages available, OGNL, MVEL, and JBoss
|
||||
EL, to name a few, the Spring Expression Language was created to provide the Spring
|
||||
While there are several other Java expression languages available -- OGNL, MVEL, and JBoss
|
||||
EL, to name a few -- the Spring Expression Language was created to provide the Spring
|
||||
community with a single well supported expression language that can be used across all
|
||||
the products in the Spring portfolio. Its language features are driven by the
|
||||
requirements of the projects in the Spring portfolio, including tooling requirements for
|
||||
code completion support within the eclipse based Spring Tool Suite. That said,
|
||||
code completion support within the Eclipse based Spring Tool Suite. That said,
|
||||
SpEL is based on a technology agnostic API allowing other expression language
|
||||
implementations to be integrated should the need arise.
|
||||
|
||||
|
|
@ -29,10 +29,10 @@ infrastructure classes such as the parser. Most Spring users will not need to de
|
|||
this infrastructure and will instead only author expression strings for evaluation. An
|
||||
example of this typical use is the integration of SpEL into creating XML or annotated
|
||||
based bean definitions as shown in the section <<expressions-beandef,Expression support
|
||||
for defining bean definitions.>>
|
||||
for defining bean definitions>>.
|
||||
|
||||
This chapter covers the features of the expression language, its API, and its language
|
||||
syntax. In several places an Inventor and Inventor's Society class are used as the
|
||||
syntax. In several places an `Inventor` and Inventor's `Society` classes are used as the
|
||||
target objects for expression evaluation. These class declarations and the data used to
|
||||
populate them are listed at the end of the chapter.
|
||||
|
||||
|
|
@ -82,7 +82,7 @@ The following code introduces the SpEL API to evaluate the literal string expres
|
|||
The value of the message variable is simply 'Hello World'.
|
||||
|
||||
The SpEL classes and interfaces you are most likely to use are located in the packages
|
||||
`org.springframework.expression` and its sub packages and `spel.support`.
|
||||
`org.springframework.expression` and its sub packages such as `spel.support`.
|
||||
|
||||
The interface `ExpressionParser` is responsible for parsing an expression string. In
|
||||
this example the expression string is a string literal denoted by the surrounding single
|
||||
|
|
@ -119,8 +119,8 @@ as shown below.
|
|||
byte[] bytes = (byte[]) exp.getValue();
|
||||
----
|
||||
|
||||
SpEL also supports nested properties using standard _dot_ notation, i.e.
|
||||
prop1.prop2.prop3 and the setting of property values
|
||||
SpEL also supports nested properties using the standard _dot_ notation, i.e.
|
||||
`prop1.prop2.prop3` and also the corresponding setting of property values.
|
||||
|
||||
Public fields may also be accessed.
|
||||
|
||||
|
|
@ -181,36 +181,35 @@ create a boolean condition:
|
|||
=== `EvaluationContext`
|
||||
|
||||
The interface `EvaluationContext` is used when evaluating an expression to resolve
|
||||
properties, methods, fields, and to help perform type conversion. There are two
|
||||
properties, methods, or fields and to help perform type conversion. There are two
|
||||
out-of-the-box implementations.
|
||||
|
||||
* `SimpleEvaluationContext` -- exposes a subset of essential SpEL language features and
|
||||
configuration options, for categories of expressions that do not require the full extent
|
||||
of the SpEL language syntax and should be meaningfully restricted. Examples
|
||||
include but are not limited to data binding expressions, property-based filters, and
|
||||
others.
|
||||
of the SpEL language syntax and should be meaningfully restricted. Examples include but
|
||||
are not limited to data binding expressions, property-based filters, and others.
|
||||
|
||||
* `StandardEvaluationContext` -- exposes the full set of SpEL language features and
|
||||
configuration options. You may use it to specify a default root object, and to configure
|
||||
configuration options. You may use it to specify a default root object and to configure
|
||||
every available evaluation-related strategy.
|
||||
|
||||
`SimpleEvaluationContext` is designed to support only a subset of the SpEL language syntax.
|
||||
It excludes Java type references, constructors, and bean references. It also requires
|
||||
explicit choosing the level of support for properties and methods in expressions.
|
||||
It _excludes_ Java type references, constructors, and bean references. It also requires
|
||||
that one explicitly choose the level of support for properties and methods in expressions.
|
||||
By default, the `create()` static factory method enables only read access to properties.
|
||||
You can also obtain a builder to configure the exact level of support needed, targeting
|
||||
one of, or some combination of the following:
|
||||
one or some combination of the following:
|
||||
|
||||
. Custom `PropertyAccessor` only (no reflection).
|
||||
. Data binding properties for read-only access.
|
||||
. Data binding properties for read and write.
|
||||
. Custom `PropertyAccessor` only (no reflection)
|
||||
. Data binding properties for read-only access
|
||||
. Data binding properties for read and write
|
||||
|
||||
|
||||
[[expressions-type-conversion]]
|
||||
==== Type conversion
|
||||
|
||||
By default SpEL uses the conversion service available in Spring core (
|
||||
`org.springframework.core.convert.ConversionService`). This conversion service comes
|
||||
By default SpEL uses the conversion service available in Spring core
|
||||
(`org.springframework.core.convert.ConversionService`). This conversion service comes
|
||||
with many converters built in for common conversions but is also fully extensible so
|
||||
custom conversions between types can be added. Additionally it has the key capability
|
||||
that it is generics aware. This means that when working with generic types in
|
||||
|
|
@ -289,22 +288,21 @@ It is also possible to configure the behaviour of the SpEL expression compiler.
|
|||
|
||||
Spring Framework 4.1 includes a basic expression compiler. Expressions are usually
|
||||
interpreted which provides a lot of dynamic flexibility during evaluation but
|
||||
does not provide the optimum performance. For occasional expression usage
|
||||
does not provide optimum performance. For occasional expression usage
|
||||
this is fine, but when used by other components like Spring Integration,
|
||||
performance can be very important and there is no real need for the dynamism.
|
||||
|
||||
The new SpEL compiler is intended to address this need. The
|
||||
compiler will generate a real Java class on the fly during evaluation that embodies the
|
||||
expression behavior and use that to achieve much faster expression
|
||||
evaluation. Due to the lack of typing around expressions the compiler
|
||||
uses information gathered during the interpreted evaluations of an
|
||||
expression when performing compilation. For example, it does not know the type
|
||||
of a property reference purely from the expression but during the first
|
||||
interpreted evaluation it will find out what it is. Of course, basing the
|
||||
compilation on this information could cause trouble later if the types of
|
||||
the various expression elements change over time. For this reason compilation
|
||||
is best suited to expressions whose type information is not going to change
|
||||
on repeated evaluations.
|
||||
The SpEL compiler is intended to address this need. The compiler will generate a
|
||||
real Java class on the fly during evaluation that embodies the expression behavior
|
||||
and use that to achieve much faster expression evaluation. Due to the lack of
|
||||
typing around expressions the compiler uses information gathered during the
|
||||
interpreted evaluations of an expression when performing compilation. For example,
|
||||
it does not know the type of a property reference purely from the expression but
|
||||
during the first interpreted evaluation it will find out what it is. Of course,
|
||||
basing the compilation on this information could cause trouble later if the types
|
||||
of the various expression elements change over time. For this reason compilation
|
||||
is best suited to expressions whose type information is not going to change on
|
||||
repeated evaluations.
|
||||
|
||||
For a basic expression like this:
|
||||
|
||||
|
|
@ -365,24 +363,22 @@ After selecting a mode, use the `SpelParserConfiguration` to configure the parse
|
|||
When specifying the compiler mode it is also possible to specify a classloader (passing null is allowed).
|
||||
Compiled expressions will be defined in a child classloader created under any that is supplied.
|
||||
It is important to ensure if a classloader is specified it can see all the types involved in
|
||||
the expression evaluation process.
|
||||
If none is specified then a default classloader will be used (typically the context classloader for
|
||||
the thread that is running during expression evaluation).
|
||||
the expression evaluation process. If none is specified then a default classloader will be used
|
||||
(typically the context classloader for the thread that is running during expression evaluation).
|
||||
|
||||
The second way to configure the compiler is for use when SpEL is embedded inside some other
|
||||
component and it may not be possible to configure via a configuration object.
|
||||
In these cases it is possible to use a system property. The property
|
||||
`spring.expression.compiler.mode` can be set to one of the `SpelCompilerMode`
|
||||
enum values (`off`, `immediate`, or `mixed`).
|
||||
component and it may not be possible to configure via a configuration object. In these cases
|
||||
it is possible to use a system property. The property `spring.expression.compiler.mode` can be
|
||||
set to one of the `SpelCompilerMode` enum values (`off`, `immediate`, or `mixed`).
|
||||
|
||||
|
||||
[[expressions-compiler-limitations]]
|
||||
==== Compiler limitations
|
||||
|
||||
With Spring Framework 4.1 the basic compilation framework is in place. However, the framework does not
|
||||
yet support compiling every kind of expression. The initial focus has been on the common expressions that are
|
||||
likely to be used in performance critical contexts. These kinds of expression cannot be compiled
|
||||
at the moment:
|
||||
Since Spring Framework 4.1 the basic compilation framework is in place. However, the framework
|
||||
does not yet support compiling every kind of expression. The initial focus has been on the
|
||||
common expressions that are likely to be used in performance critical contexts. The following
|
||||
kinds of expression cannot be compiled at the moment:
|
||||
|
||||
- expressions involving assignment
|
||||
- expressions relying on the conversion service
|
||||
|
|
@ -608,7 +604,7 @@ arrays and lists are obtained using square bracket notation.
|
|||
[subs="verbatim,quotes"]
|
||||
----
|
||||
ExpressionParser parser = new SpelExpressionParser();
|
||||
SimpleEvaluationContext context = SimpleEvaluationContext.create();
|
||||
EvaluationContext context = SimpleEvaluationContext.forReadOnlyDataBinding().build();
|
||||
|
||||
// Inventions Array
|
||||
|
||||
|
|
@ -779,11 +775,11 @@ expression based `matches` operator.
|
|||
|
||||
// evaluates to true
|
||||
boolean trueValue = parser.parseExpression(
|
||||
"'5.00' matches '\^-?\\d+(\\.\\d{2})?$'").getValue(Boolean.class);
|
||||
"'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);
|
||||
"'5.0067' matches '^-?\\d+(\\.\\d{2})?$'").getValue(Boolean.class);
|
||||
----
|
||||
|
||||
[NOTE]
|
||||
|
|
@ -796,7 +792,7 @@ evaluates to `true`, as expected.
|
|||
Each symbolic operator can also be specified as a purely alphabetic equivalent. This
|
||||
avoids problems where the symbols used have special meaning for the document type in
|
||||
which the expression is embedded (eg. an XML document). The textual equivalents are
|
||||
shown here: `lt` (`<`), `gt` (`>`), `le` (`<=`), `ge` (`>=`), `eq` (`==`),
|
||||
shown here: `lt` (`<`), `gt` (`>`), `le` (`\<=`), `ge` (`>=`), `eq` (`==`),
|
||||
`ne` (`!=`), `div` (`/`), `mod` (`%`), `not` (`!`). These are case insensitive.
|
||||
|
||||
|
||||
|
|
@ -850,33 +846,33 @@ operators are demonstrated below.
|
|||
[subs="verbatim,quotes"]
|
||||
----
|
||||
// Addition
|
||||
int two = parser.parseExpression("1 + 1").getValue(Integer.class); // 2
|
||||
int two = parser.parseExpression("1 + 1").getValue(Integer.class); // 2
|
||||
|
||||
String testString = parser.parseExpression(
|
||||
"'test' + ' ' + 'string'").getValue(String.class); // 'test string'
|
||||
"'test' + ' ' + 'string'").getValue(String.class); // 'test string'
|
||||
|
||||
// Subtraction
|
||||
int four = parser.parseExpression("1 - -3").getValue(Integer.class); // 4
|
||||
int four = parser.parseExpression("1 - -3").getValue(Integer.class); // 4
|
||||
|
||||
double d = parser.parseExpression("1000.00 - 1e4").getValue(Double.class); // -9000
|
||||
double d = parser.parseExpression("1000.00 - 1e4").getValue(Double.class); // -9000
|
||||
|
||||
// Multiplication
|
||||
int six = parser.parseExpression("-2 * -3").getValue(Integer.class); // 6
|
||||
int six = parser.parseExpression("-2 * -3").getValue(Integer.class); // 6
|
||||
|
||||
double twentyFour = parser.parseExpression("2.0 * 3e0 * 4").getValue(Double.class); // 24.0
|
||||
double twentyFour = parser.parseExpression("2.0 * 3e0 * 4").getValue(Double.class); // 24.0
|
||||
|
||||
// Division
|
||||
int minusTwo = parser.parseExpression("6 / -3").getValue(Integer.class); // -2
|
||||
int minusTwo = parser.parseExpression("6 / -3").getValue(Integer.class); // -2
|
||||
|
||||
double one = parser.parseExpression("8.0 / 4e0 / 2").getValue(Double.class); // 1.0
|
||||
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 three = parser.parseExpression("7 % 4").getValue(Integer.class); // 3
|
||||
|
||||
int one = parser.parseExpression("8 / 5 % 2").getValue(Integer.class); // 1
|
||||
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
|
||||
int minusTwentyOne = parser.parseExpression("1+2-3*8").getValue(Integer.class); // -21
|
||||
----
|
||||
|
||||
|
||||
|
|
@ -891,14 +887,13 @@ done within a call to `setValue` but can also be done inside a call to `getValue
|
|||
[subs="verbatim,quotes"]
|
||||
----
|
||||
Inventor inventor = new Inventor();
|
||||
SimpleEvaluationContext context = SimpleEvaluationContext.create();
|
||||
EvaluationContext context = SimpleEvaluationContext.forReadWriteDataBinding().build();
|
||||
|
||||
parser.parseExpression("Name").setValue(context, inventor, "Alexander Seovic2");
|
||||
parser.parseExpression("Name").setValue(context, inventor, "Aleksandar Seovic");
|
||||
|
||||
// alternatively
|
||||
|
||||
String aleks = parser.parseExpression(
|
||||
"Name = 'Alexandar Seovic'").getValue(context, inventor, String.class);
|
||||
"Name = 'Aleksandar Seovic'").getValue(context, inventor, String.class);
|
||||
----
|
||||
|
||||
|
||||
|
|
@ -953,28 +948,28 @@ used).
|
|||
=== Variables
|
||||
|
||||
Variables can be referenced in the expression using the syntax `#variableName`. Variables
|
||||
are set using the method setVariable on `EvaluationContext` implementations.
|
||||
are set using the method `setVariable` on `EvaluationContext` implementations.
|
||||
|
||||
[source,java,indent=0]
|
||||
[subs="verbatim,quotes"]
|
||||
----
|
||||
Inventor tesla = new Inventor("Nikola Tesla", "Serbian");
|
||||
SimpleEvaluationContext context = SimpleEvaluationContext.create();
|
||||
|
||||
EvaluationContext context = SimpleEvaluationContext.forReadWriteDataBinding().build();
|
||||
context.setVariable("newName", "Mike Tesla");
|
||||
|
||||
parser.parseExpression("Name = #newName").getValue(context, tesla);
|
||||
|
||||
System.out.println(tesla.getName()) // "Mike Tesla"
|
||||
System.out.println(tesla.getName()) // "Mike Tesla"
|
||||
----
|
||||
|
||||
|
||||
[[expressions-this-root]]
|
||||
==== The #this and #root variables
|
||||
|
||||
The variable #this is always defined and refers to the current evaluation object
|
||||
(against which unqualified references are resolved). The variable #root is always
|
||||
defined and refers to the root context object. Although #this may vary as components of
|
||||
an expression are evaluated, #root always refers to the root.
|
||||
The variable `#this` is always defined and refers to the current evaluation object
|
||||
(against which unqualified references are resolved). The variable `#root` is always
|
||||
defined and refers to the root context object. Although `#this` may vary as components of
|
||||
an expression are evaluated, `#root` always refers to the root.
|
||||
|
||||
[source,java,indent=0]
|
||||
[subs="verbatim,quotes"]
|
||||
|
|
@ -985,8 +980,8 @@ an expression are evaluated, #root always refers to the root.
|
|||
|
||||
// create parser and set variable 'primes' as the array of integers
|
||||
ExpressionParser parser = new SpelExpressionParser();
|
||||
SimpleEvaluationContext context = SimpleEvaluationContext.create();
|
||||
context.setVariable("primes",primes);
|
||||
EvaluationContext context = SimpleEvaluationContext.forReadOnlyDataAccess();
|
||||
context.setVariable("primes", primes);
|
||||
|
||||
// all prime numbers > 10 from the list (using selection ?{...})
|
||||
// evaluates to [11, 13, 17]
|
||||
|
|
@ -1007,7 +1002,7 @@ expression string. The function is registered through the `EvaluationContext`.
|
|||
----
|
||||
Method method = ...;
|
||||
|
||||
SimpleEvaluationContext context = SimpleEvaluationContext.create();
|
||||
EvaluationContext context = SimpleEvaluationContext.forReadOnlyDataBinding().build();
|
||||
context.setVariable("myFunction", method);
|
||||
----
|
||||
|
||||
|
|
@ -1019,7 +1014,7 @@ For example, given a utility method to reverse a string is shown below:
|
|||
public abstract class StringUtils {
|
||||
|
||||
public static String reverseString(String input) {
|
||||
StringBuilder backwards = new StringBuilder();
|
||||
StringBuilder backwards = new StringBuilder(input.length());
|
||||
for (int i = 0; i < input.length(); i++)
|
||||
backwards.append(input.charAt(input.length() - 1 - i));
|
||||
}
|
||||
|
|
@ -1034,13 +1029,13 @@ The above method can then be registered and used as follows:
|
|||
[subs="verbatim,quotes"]
|
||||
----
|
||||
ExpressionParser parser = new SpelExpressionParser();
|
||||
SimpleEvaluationContext context = SimpleEvaluationContext.create();
|
||||
|
||||
EvaluationContext context = SimpleEvaluationContext.forReadOnlyDataBinding().build();
|
||||
context.setVariable("reverseString",
|
||||
StringUtils.class.getDeclaredMethod("reverseString", String.class));
|
||||
StringUtils.class.getDeclaredMethod("reverseString", String.class));
|
||||
|
||||
String helloWorldReversed = parser.parseExpression(
|
||||
"#reverseString('hello')").getValue(context, String.class);
|
||||
"#reverseString('hello')").getValue(context, String.class);
|
||||
----
|
||||
|
||||
|
||||
|
|
@ -1049,26 +1044,26 @@ The above method can then be registered and used as follows:
|
|||
=== Bean references
|
||||
|
||||
If the evaluation context has been configured with a bean resolver it is possible to
|
||||
lookup beans from an expression using the (@) symbol.
|
||||
look up beans from an expression using the `@` symbol.
|
||||
|
||||
[source,java,indent=0]
|
||||
[subs="verbatim,quotes"]
|
||||
----
|
||||
ExpressionParser parser = new SpelExpressionParser();
|
||||
StandardEvaluationContext context = StandardEvaluationContext.create();
|
||||
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);
|
||||
----
|
||||
|
||||
To access a factory bean itself, the bean name should instead be prefixed with a (&) symbol.
|
||||
To access a factory bean itself, the bean name should instead be prefixed with an `&` symbol.
|
||||
|
||||
[source,java,indent=0]
|
||||
[subs="verbatim,quotes"]
|
||||
----
|
||||
ExpressionParser parser = new SpelExpressionParser();
|
||||
StandardEvaluationContext context = StandardEvaluationContext.create();
|
||||
StandardEvaluationContext context = new StandardEvaluationContext();
|
||||
context.setBeanResolver(new MyBeanResolver());
|
||||
|
||||
// This will end up calling resolve(context,"&foo") on MyBeanResolver during evaluation
|
||||
|
|
@ -1089,8 +1084,8 @@ the expression. A minimal example is:
|
|||
"false ? 'trueExp' : 'falseExp'").getValue(String.class);
|
||||
----
|
||||
|
||||
In this case, the boolean false results in returning the string value 'falseExp'. A more
|
||||
realistic example is shown below.
|
||||
In this case, the boolean false results in returning the string value `'falseExp'`.
|
||||
A more realistic example is shown below.
|
||||
|
||||
[source,java,indent=0]
|
||||
[subs="verbatim,quotes"]
|
||||
|
|
@ -1114,19 +1109,20 @@ ternary operator.
|
|||
[[expressions-operator-elvis]]
|
||||
=== The Elvis Operator
|
||||
|
||||
The Elvis operator is a shortening of the ternary operator syntax and is used in the
|
||||
http://www.groovy-lang.org/operators.html#_elvis_operator[Groovy] language.
|
||||
With the ternary operator syntax you usually have to repeat a variable twice, for
|
||||
example:
|
||||
The Elvis operator is a shortening of the ternary operator syntax and is used in
|
||||
the http://www.groovy-lang.org/operators.html#_elvis_operator[Groovy] language.
|
||||
With the ternary operator syntax, you usually have to repeat a variable twice,
|
||||
as the following example shows:
|
||||
|
||||
[source,groovy,indent=0]
|
||||
[subs="verbatim,quotes"]
|
||||
----
|
||||
String name = "Elvis Presley";
|
||||
String displayName = name != null ? name : "Unknown";
|
||||
String displayName = (name != null ? name : "Unknown");
|
||||
----
|
||||
|
||||
Instead you can use the Elvis operator, named for the resemblance to Elvis' hair style.
|
||||
Instead, you can use the Elvis operator (named for the resemblance to Elvis' hair style).
|
||||
The following example shows how to use the Elvis operator:
|
||||
|
||||
[source,java,indent=0]
|
||||
[subs="verbatim,quotes"]
|
||||
|
|
@ -1134,29 +1130,24 @@ Instead you can use the Elvis operator, named for the resemblance to Elvis' hair
|
|||
ExpressionParser parser = new SpelExpressionParser();
|
||||
|
||||
String name = parser.parseExpression("name?:'Unknown'").getValue(String.class);
|
||||
|
||||
System.out.println(name); // 'Unknown'
|
||||
System.out.println(name); // 'Unknown'
|
||||
----
|
||||
|
||||
Here is a more complex example.
|
||||
The following listing shows a more complex example:
|
||||
|
||||
[source,java,indent=0]
|
||||
[subs="verbatim,quotes"]
|
||||
----
|
||||
ExpressionParser parser = new SpelExpressionParser();
|
||||
EvaluationContext context = SimpleEvaluationContext.forReadOnlyDataBinding().build();
|
||||
|
||||
Inventor tesla = new Inventor("Nikola Tesla", "Serbian");
|
||||
SimpleEvaluationContext context = SimpleEvaluationContext.create();
|
||||
|
||||
String name = parser.parseExpression("Name?:'Elvis Presley'").getValue(context, tesla, String.class);
|
||||
|
||||
System.out.println(name); // Nikola Tesla
|
||||
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
|
||||
System.out.println(name); // Elvis Presley
|
||||
----
|
||||
|
||||
|
||||
|
|
@ -1174,20 +1165,17 @@ safe navigation operator will simply return null instead of throwing an exceptio
|
|||
[subs="verbatim,quotes"]
|
||||
----
|
||||
ExpressionParser parser = new SpelExpressionParser();
|
||||
EvaluationContext context = SimpleEvaluationContext.forReadOnlyDataBinding().build();
|
||||
|
||||
Inventor tesla = new Inventor("Nikola Tesla", "Serbian");
|
||||
tesla.setPlaceOfBirth(new PlaceOfBirth("Smiljan"));
|
||||
|
||||
SimpleEvaluationContext context = SimpleEvaluationContext.create();
|
||||
|
||||
String city = parser.parseExpression("PlaceOfBirth?.City").getValue(context, tesla, String.class);
|
||||
System.out.println(city); // Smiljan
|
||||
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!!!
|
||||
System.out.println(city); // null - does not throw NullPointerException!!!
|
||||
----
|
||||
|
||||
[NOTE]
|
||||
|
|
@ -1240,7 +1228,8 @@ where the entry value is less than 27.
|
|||
|
||||
In addition to returning all the selected elements, it is possible to retrieve just the
|
||||
first or the last value. To obtain the first entry matching the selection the syntax is
|
||||
`^[...]` whilst to obtain the last matching selection the syntax is `$[...]`.
|
||||
`.^[selectionExpression]` whilst to obtain the last matching selection the syntax is
|
||||
`.$[selectionExpression]`.
|
||||
|
||||
|
||||
|
||||
|
|
@ -1248,9 +1237,9 @@ first or the last value. To obtain the first entry matching the selection the sy
|
|||
=== Collection Projection
|
||||
|
||||
Projection allows a collection to drive the evaluation of a sub-expression and the
|
||||
result is a new collection. The syntax for projection is `![projectionExpression]`. Most
|
||||
easily understood by example, suppose we have a list of inventors but want the list of
|
||||
cities where they were born. Effectively we want to evaluate 'placeOfBirth.city' for
|
||||
result is a new collection. The syntax for projection is `.![projectionExpression]`.
|
||||
Most easily understood by example, suppose we have a list of inventors but want the list
|
||||
of cities where they were born. Effectively we want to evaluate 'placeOfBirth.city' for
|
||||
every entry in the inventor list. Using projection:
|
||||
|
||||
[source,java,indent=0]
|
||||
|
|
@ -1284,9 +1273,9 @@ define, a common choice is to use `#{ }` as the delimiters. For example,
|
|||
// evaluates to "random number is 0.7038186818312008"
|
||||
----
|
||||
|
||||
The string is evaluated by concatenating the literal text 'random number is ' with the
|
||||
result of evaluating the expression inside the #{ } delimiter, in this case the result
|
||||
of calling that random() method. The second argument to the method `parseExpression()`
|
||||
The string is evaluated by concatenating the literal text `'random number is '` with the
|
||||
result of evaluating the expression inside the `#{ }` delimiter, in this case the result
|
||||
of calling that `random()` method. The second argument to the method `parseExpression()`
|
||||
is of the type `ParserContext`. The `ParserContext` interface is used to influence how
|
||||
the expression is parsed in order to support the expression templating functionality.
|
||||
The definition of `TemplateParserContext` is shown below.
|
||||
|
|
|
|||
Loading…
Reference in New Issue