Minor documentation refinements (backported from 5.1.x)
This commit is contained in:
@@ -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;
|
package org.springframework.messaging.simp;
|
||||||
|
|||||||
@@ -7,17 +7,17 @@
|
|||||||
[[expressions-intro]]
|
[[expressions-intro]]
|
||||||
== Introduction
|
== 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
|
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
|
similar to Unified EL but offers additional features, most notably method invocation and
|
||||||
basic string templating functionality.
|
basic string templating functionality.
|
||||||
|
|
||||||
While there are several other Java expression languages available, OGNL, MVEL, and JBoss
|
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
|
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
|
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
|
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
|
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
|
SpEL is based on a technology agnostic API allowing other expression language
|
||||||
implementations to be integrated should the need arise.
|
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
|
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
|
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
|
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
|
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
|
target objects for expression evaluation. These class declarations and the data used to
|
||||||
populate them are listed at the end of the chapter.
|
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 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
|
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
|
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
|
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();
|
byte[] bytes = (byte[]) exp.getValue();
|
||||||
----
|
----
|
||||||
|
|
||||||
SpEL also supports nested properties using standard _dot_ notation, i.e.
|
SpEL also supports nested properties using the standard _dot_ notation, i.e.
|
||||||
prop1.prop2.prop3 and the setting of property values
|
`prop1.prop2.prop3` and also the corresponding setting of property values.
|
||||||
|
|
||||||
Public fields may also be accessed.
|
Public fields may also be accessed.
|
||||||
|
|
||||||
@@ -181,36 +181,35 @@ create a boolean condition:
|
|||||||
=== `EvaluationContext`
|
=== `EvaluationContext`
|
||||||
|
|
||||||
The interface `EvaluationContext` is used when evaluating an expression to resolve
|
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.
|
out-of-the-box implementations.
|
||||||
|
|
||||||
* `SimpleEvaluationContext` -- exposes a subset of essential SpEL language features and
|
* `SimpleEvaluationContext` -- exposes a subset of essential SpEL language features and
|
||||||
configuration options, for categories of expressions that do not require the full extent
|
configuration options, for categories of expressions that do not require the full extent
|
||||||
of the SpEL language syntax and should be meaningfully restricted. Examples
|
of the SpEL language syntax and should be meaningfully restricted. Examples include but
|
||||||
include but are not limited to data binding expressions, property-based filters, and
|
are not limited to data binding expressions, property-based filters, and others.
|
||||||
others.
|
|
||||||
|
|
||||||
* `StandardEvaluationContext` -- exposes the full set of SpEL language features and
|
* `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.
|
every available evaluation-related strategy.
|
||||||
|
|
||||||
`SimpleEvaluationContext` is designed to support only a subset of the SpEL language syntax.
|
`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
|
It _excludes_ Java type references, constructors, and bean references. It also requires
|
||||||
explicit choosing the level of support for properties and methods in expressions.
|
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.
|
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
|
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).
|
. Custom `PropertyAccessor` only (no reflection)
|
||||||
. Data binding properties for read-only access.
|
. Data binding properties for read-only access
|
||||||
. Data binding properties for read and write.
|
. Data binding properties for read and write
|
||||||
|
|
||||||
|
|
||||||
[[expressions-type-conversion]]
|
[[expressions-type-conversion]]
|
||||||
==== Type conversion
|
==== Type conversion
|
||||||
|
|
||||||
By default SpEL uses the conversion service available in Spring core (
|
By default SpEL uses the conversion service available in Spring core
|
||||||
`org.springframework.core.convert.ConversionService`). This conversion service comes
|
(`org.springframework.core.convert.ConversionService`). This conversion service comes
|
||||||
with many converters built in for common conversions but is also fully extensible so
|
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
|
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
|
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
|
Spring Framework 4.1 includes a basic expression compiler. Expressions are usually
|
||||||
interpreted which provides a lot of dynamic flexibility during evaluation but
|
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,
|
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.
|
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
|
The SpEL compiler is intended to address this need. The compiler will generate a
|
||||||
compiler will generate a real Java class on the fly during evaluation that embodies the
|
real Java class on the fly during evaluation that embodies the expression behavior
|
||||||
expression behavior and use that to achieve much faster expression
|
and use that to achieve much faster expression evaluation. Due to the lack of
|
||||||
evaluation. Due to the lack of typing around expressions the compiler
|
typing around expressions the compiler uses information gathered during the
|
||||||
uses information gathered during the interpreted evaluations of an
|
interpreted evaluations of an expression when performing compilation. For example,
|
||||||
expression when performing compilation. For example, it does not know the type
|
it does not know the type of a property reference purely from the expression but
|
||||||
of a property reference purely from the expression but during the first
|
during the first interpreted evaluation it will find out what it is. Of course,
|
||||||
interpreted evaluation it will find out what it is. Of course, basing the
|
basing the compilation on this information could cause trouble later if the types
|
||||||
compilation on this information could cause trouble later if the types of
|
of the various expression elements change over time. For this reason compilation
|
||||||
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
|
||||||
is best suited to expressions whose type information is not going to change
|
repeated evaluations.
|
||||||
on repeated evaluations.
|
|
||||||
|
|
||||||
For a basic expression like this:
|
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).
|
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.
|
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
|
It is important to ensure if a classloader is specified it can see all the types involved in
|
||||||
the expression evaluation process.
|
the expression evaluation process. If none is specified then a default classloader will be used
|
||||||
If none is specified then a default classloader will be used (typically the context classloader for
|
(typically the context classloader for the thread that is running during expression evaluation).
|
||||||
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
|
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.
|
component and it may not be possible to configure via a configuration object. In these cases
|
||||||
In these cases it is possible to use a system property. The property
|
it is possible to use a system property. The property `spring.expression.compiler.mode` can be
|
||||||
`spring.expression.compiler.mode` can be set to one of the `SpelCompilerMode`
|
set to one of the `SpelCompilerMode` enum values (`off`, `immediate`, or `mixed`).
|
||||||
enum values (`off`, `immediate`, or `mixed`).
|
|
||||||
|
|
||||||
|
|
||||||
[[expressions-compiler-limitations]]
|
[[expressions-compiler-limitations]]
|
||||||
==== Compiler limitations
|
==== Compiler limitations
|
||||||
|
|
||||||
With Spring Framework 4.1 the basic compilation framework is in place. However, the framework does not
|
Since Spring Framework 4.1 the basic compilation framework is in place. However, the framework
|
||||||
yet support compiling every kind of expression. The initial focus has been on the common expressions that are
|
does not yet support compiling every kind of expression. The initial focus has been on the
|
||||||
likely to be used in performance critical contexts. These kinds of expression cannot be compiled
|
common expressions that are likely to be used in performance critical contexts. The following
|
||||||
at the moment:
|
kinds of expression cannot be compiled at the moment:
|
||||||
|
|
||||||
- expressions involving assignment
|
- expressions involving assignment
|
||||||
- expressions relying on the conversion service
|
- expressions relying on the conversion service
|
||||||
@@ -608,7 +604,7 @@ arrays and lists are obtained using square bracket notation.
|
|||||||
[subs="verbatim,quotes"]
|
[subs="verbatim,quotes"]
|
||||||
----
|
----
|
||||||
ExpressionParser parser = new SpelExpressionParser();
|
ExpressionParser parser = new SpelExpressionParser();
|
||||||
SimpleEvaluationContext context = SimpleEvaluationContext.create();
|
EvaluationContext context = SimpleEvaluationContext.forReadOnlyDataBinding().build();
|
||||||
|
|
||||||
// Inventions Array
|
// Inventions Array
|
||||||
|
|
||||||
@@ -779,11 +775,11 @@ expression based `matches` operator.
|
|||||||
|
|
||||||
// evaluates to true
|
// evaluates to true
|
||||||
boolean trueValue = parser.parseExpression(
|
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
|
//evaluates to false
|
||||||
boolean falseValue = parser.parseExpression(
|
boolean falseValue = parser.parseExpression(
|
||||||
"'5.0067' matches '\^-?\\d+(\\.\\d{2})?$'").getValue(Boolean.class);
|
"'5.0067' matches '^-?\\d+(\\.\\d{2})?$'").getValue(Boolean.class);
|
||||||
----
|
----
|
||||||
|
|
||||||
[NOTE]
|
[NOTE]
|
||||||
@@ -796,7 +792,7 @@ evaluates to `true`, as expected.
|
|||||||
Each symbolic operator can also be specified as a purely alphabetic equivalent. This
|
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
|
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
|
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.
|
`ne` (`!=`), `div` (`/`), `mod` (`%`), `not` (`!`). These are case insensitive.
|
||||||
|
|
||||||
|
|
||||||
@@ -850,33 +846,33 @@ operators are demonstrated below.
|
|||||||
[subs="verbatim,quotes"]
|
[subs="verbatim,quotes"]
|
||||||
----
|
----
|
||||||
// Addition
|
// 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(
|
String testString = parser.parseExpression(
|
||||||
"'test' + ' ' + 'string'").getValue(String.class); // 'test string'
|
"'test' + ' ' + 'string'").getValue(String.class); // 'test string'
|
||||||
|
|
||||||
// Subtraction
|
// 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
|
// 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
|
// 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
|
// 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
|
// 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"]
|
[subs="verbatim,quotes"]
|
||||||
----
|
----
|
||||||
Inventor inventor = new Inventor();
|
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
|
// alternatively
|
||||||
|
|
||||||
String aleks = parser.parseExpression(
|
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
|
||||||
|
|
||||||
Variables can be referenced in the expression using the syntax `#variableName`. 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]
|
[source,java,indent=0]
|
||||||
[subs="verbatim,quotes"]
|
[subs="verbatim,quotes"]
|
||||||
----
|
----
|
||||||
Inventor tesla = new Inventor("Nikola Tesla", "Serbian");
|
Inventor tesla = new Inventor("Nikola Tesla", "Serbian");
|
||||||
SimpleEvaluationContext context = SimpleEvaluationContext.create();
|
|
||||||
|
EvaluationContext context = SimpleEvaluationContext.forReadWriteDataBinding().build();
|
||||||
context.setVariable("newName", "Mike Tesla");
|
context.setVariable("newName", "Mike Tesla");
|
||||||
|
|
||||||
parser.parseExpression("Name = #newName").getValue(context, 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]]
|
[[expressions-this-root]]
|
||||||
==== The #this and #root variables
|
==== The #this and #root variables
|
||||||
|
|
||||||
The variable #this is always defined and refers to the current evaluation object
|
The variable `#this` is always defined and refers to the current evaluation object
|
||||||
(against which unqualified references are resolved). The variable #root is always
|
(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
|
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.
|
an expression are evaluated, `#root` always refers to the root.
|
||||||
|
|
||||||
[source,java,indent=0]
|
[source,java,indent=0]
|
||||||
[subs="verbatim,quotes"]
|
[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
|
// create parser and set variable 'primes' as the array of integers
|
||||||
ExpressionParser parser = new SpelExpressionParser();
|
ExpressionParser parser = new SpelExpressionParser();
|
||||||
SimpleEvaluationContext context = SimpleEvaluationContext.create();
|
EvaluationContext context = SimpleEvaluationContext.forReadOnlyDataAccess();
|
||||||
context.setVariable("primes",primes);
|
context.setVariable("primes", primes);
|
||||||
|
|
||||||
// all prime numbers > 10 from the list (using selection ?{...})
|
// all prime numbers > 10 from the list (using selection ?{...})
|
||||||
// evaluates to [11, 13, 17]
|
// evaluates to [11, 13, 17]
|
||||||
@@ -1007,7 +1002,7 @@ expression string. The function is registered through the `EvaluationContext`.
|
|||||||
----
|
----
|
||||||
Method method = ...;
|
Method method = ...;
|
||||||
|
|
||||||
SimpleEvaluationContext context = SimpleEvaluationContext.create();
|
EvaluationContext context = SimpleEvaluationContext.forReadOnlyDataBinding().build();
|
||||||
context.setVariable("myFunction", method);
|
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 abstract class StringUtils {
|
||||||
|
|
||||||
public static String reverseString(String input) {
|
public static String reverseString(String input) {
|
||||||
StringBuilder backwards = new StringBuilder();
|
StringBuilder backwards = new StringBuilder(input.length());
|
||||||
for (int i = 0; i < input.length(); i++)
|
for (int i = 0; i < input.length(); i++)
|
||||||
backwards.append(input.charAt(input.length() - 1 - 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"]
|
[subs="verbatim,quotes"]
|
||||||
----
|
----
|
||||||
ExpressionParser parser = new SpelExpressionParser();
|
ExpressionParser parser = new SpelExpressionParser();
|
||||||
SimpleEvaluationContext context = SimpleEvaluationContext.create();
|
|
||||||
|
|
||||||
|
EvaluationContext context = SimpleEvaluationContext.forReadOnlyDataBinding().build();
|
||||||
context.setVariable("reverseString",
|
context.setVariable("reverseString",
|
||||||
StringUtils.class.getDeclaredMethod("reverseString", String.class));
|
StringUtils.class.getDeclaredMethod("reverseString", String.class));
|
||||||
|
|
||||||
String helloWorldReversed = parser.parseExpression(
|
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
|
=== Bean references
|
||||||
|
|
||||||
If the evaluation context has been configured with a bean resolver it is possible to
|
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]
|
[source,java,indent=0]
|
||||||
[subs="verbatim,quotes"]
|
[subs="verbatim,quotes"]
|
||||||
----
|
----
|
||||||
ExpressionParser parser = new SpelExpressionParser();
|
ExpressionParser parser = new SpelExpressionParser();
|
||||||
StandardEvaluationContext context = StandardEvaluationContext.create();
|
StandardEvaluationContext context = new StandardEvaluationContext();
|
||||||
context.setBeanResolver(new MyBeanResolver());
|
context.setBeanResolver(new MyBeanResolver());
|
||||||
|
|
||||||
// This will end up calling resolve(context,"foo") on MyBeanResolver during evaluation
|
// This will end up calling resolve(context,"foo") on MyBeanResolver during evaluation
|
||||||
Object bean = parser.parseExpression("@foo").getValue(context);
|
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]
|
[source,java,indent=0]
|
||||||
[subs="verbatim,quotes"]
|
[subs="verbatim,quotes"]
|
||||||
----
|
----
|
||||||
ExpressionParser parser = new SpelExpressionParser();
|
ExpressionParser parser = new SpelExpressionParser();
|
||||||
StandardEvaluationContext context = StandardEvaluationContext.create();
|
StandardEvaluationContext context = new StandardEvaluationContext();
|
||||||
context.setBeanResolver(new MyBeanResolver());
|
context.setBeanResolver(new MyBeanResolver());
|
||||||
|
|
||||||
// This will end up calling resolve(context,"&foo") on MyBeanResolver during evaluation
|
// 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);
|
"false ? 'trueExp' : 'falseExp'").getValue(String.class);
|
||||||
----
|
----
|
||||||
|
|
||||||
In this case, the boolean false results in returning the string value 'falseExp'. A more
|
In this case, the boolean false results in returning the string value `'falseExp'`.
|
||||||
realistic example is shown below.
|
A more realistic example is shown below.
|
||||||
|
|
||||||
[source,java,indent=0]
|
[source,java,indent=0]
|
||||||
[subs="verbatim,quotes"]
|
[subs="verbatim,quotes"]
|
||||||
@@ -1114,19 +1109,20 @@ ternary operator.
|
|||||||
[[expressions-operator-elvis]]
|
[[expressions-operator-elvis]]
|
||||||
=== The Elvis Operator
|
=== The Elvis Operator
|
||||||
|
|
||||||
The Elvis operator is a shortening of the ternary operator syntax and is used in the
|
The Elvis operator is a shortening of the ternary operator syntax and is used in
|
||||||
http://www.groovy-lang.org/operators.html#_elvis_operator[Groovy] language.
|
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
|
With the ternary operator syntax, you usually have to repeat a variable twice,
|
||||||
example:
|
as the following example shows:
|
||||||
|
|
||||||
[source,groovy,indent=0]
|
[source,groovy,indent=0]
|
||||||
[subs="verbatim,quotes"]
|
[subs="verbatim,quotes"]
|
||||||
----
|
----
|
||||||
String name = "Elvis Presley";
|
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]
|
[source,java,indent=0]
|
||||||
[subs="verbatim,quotes"]
|
[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();
|
ExpressionParser parser = new SpelExpressionParser();
|
||||||
|
|
||||||
String name = parser.parseExpression("name?:'Unknown'").getValue(String.class);
|
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]
|
[source,java,indent=0]
|
||||||
[subs="verbatim,quotes"]
|
[subs="verbatim,quotes"]
|
||||||
----
|
----
|
||||||
ExpressionParser parser = new SpelExpressionParser();
|
ExpressionParser parser = new SpelExpressionParser();
|
||||||
|
EvaluationContext context = SimpleEvaluationContext.forReadOnlyDataBinding().build();
|
||||||
|
|
||||||
Inventor tesla = new Inventor("Nikola Tesla", "Serbian");
|
Inventor tesla = new Inventor("Nikola Tesla", "Serbian");
|
||||||
SimpleEvaluationContext context = SimpleEvaluationContext.create();
|
|
||||||
|
|
||||||
String name = parser.parseExpression("Name?:'Elvis Presley'").getValue(context, tesla, String.class);
|
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);
|
tesla.setName(null);
|
||||||
|
|
||||||
name = parser.parseExpression("Name?:'Elvis Presley'").getValue(context, tesla, String.class);
|
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"]
|
[subs="verbatim,quotes"]
|
||||||
----
|
----
|
||||||
ExpressionParser parser = new SpelExpressionParser();
|
ExpressionParser parser = new SpelExpressionParser();
|
||||||
|
EvaluationContext context = SimpleEvaluationContext.forReadOnlyDataBinding().build();
|
||||||
|
|
||||||
Inventor tesla = new Inventor("Nikola Tesla", "Serbian");
|
Inventor tesla = new Inventor("Nikola Tesla", "Serbian");
|
||||||
tesla.setPlaceOfBirth(new PlaceOfBirth("Smiljan"));
|
tesla.setPlaceOfBirth(new PlaceOfBirth("Smiljan"));
|
||||||
|
|
||||||
SimpleEvaluationContext context = SimpleEvaluationContext.create();
|
|
||||||
|
|
||||||
String city = parser.parseExpression("PlaceOfBirth?.City").getValue(context, tesla, String.class);
|
String city = parser.parseExpression("PlaceOfBirth?.City").getValue(context, tesla, String.class);
|
||||||
System.out.println(city); // Smiljan
|
System.out.println(city); // Smiljan
|
||||||
|
|
||||||
tesla.setPlaceOfBirth(null);
|
tesla.setPlaceOfBirth(null);
|
||||||
|
|
||||||
city = parser.parseExpression("PlaceOfBirth?.City").getValue(context, tesla, String.class);
|
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]
|
[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
|
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
|
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
|
=== Collection Projection
|
||||||
|
|
||||||
Projection allows a collection to drive the evaluation of a sub-expression and the
|
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
|
result is a new collection. The syntax for projection is `.![projectionExpression]`.
|
||||||
easily understood by example, suppose we have a list of inventors but want the list of
|
Most easily understood by example, suppose we have a list of inventors but want the list
|
||||||
cities where they were born. Effectively we want to evaluate 'placeOfBirth.city' for
|
of cities where they were born. Effectively we want to evaluate 'placeOfBirth.city' for
|
||||||
every entry in the inventor list. Using projection:
|
every entry in the inventor list. Using projection:
|
||||||
|
|
||||||
[source,java,indent=0]
|
[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"
|
// evaluates to "random number is 0.7038186818312008"
|
||||||
----
|
----
|
||||||
|
|
||||||
The string is evaluated by concatenating the literal text 'random number is ' with the
|
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
|
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()`
|
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
|
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 expression is parsed in order to support the expression templating functionality.
|
||||||
The definition of `TemplateParserContext` is shown below.
|
The definition of `TemplateParserContext` is shown below.
|
||||||
|
|||||||
Reference in New Issue
Block a user