Expresiones literales
Se admiten los siguientes tipos de expresiones literales: cadenas, valores numéricos (int, real, hexadecimal), booleanos y nulos. Las cadenas están separadas por comillas simples. Para encerrar la comilla en una cadena, utilice dos comillas simples.
La siguiente lista muestra un uso simple de literales. Por lo general, no se usan de forma aislada, como en este caso, sino como parte de una expresión más compleja, por ejemplo, cuando se usa un literal en un lado de un operador de comparación lógica.
ExpressionParser parser = new SpelExpressionParser();
// tiene el valor "Hola mundo"
String helloWorld = (String) parser.parseExpression("'Hello World'").getValue();
double avogadrosNumber = (Double) parser.parseExpression("6.0221415E+23").getValue();
// resulta ser 2147483647
int maxValue = (Integer) parser.parseExpression("0x7FFFFFFF").getValue();
boolean trueValue = (Boolean) parser.parseExpression("true").getValue();
Object nullValue = parser.parseExpression("null").getValue();
val parser = SpelExpressionParser()
// tiene el valor "Hello World"
val helloWorld = parser.parseExpression("'Hello World'").value as String
val avogadrosNumber = parser.parseExpression("6.0221415E+23").value as Double
// resulta 2147483647
val maxValue = parser.parseExpression("0x7FFFFFFF").value as Int
val trueValue = parser.parseExpression("true").value as Boolean
val nullValue = parser.parseExpression("null").value
Los números admiten el uso de signos negativos, notación científica y puntos decimales. De forma
predeterminada, los números reales se analizan usando Double.parseDouble()
.
Propiedades, matrices, listas, matrices asociativas e indexadores
Navegue usando enlaces a Las propiedades son simples.
Para ello, utilice un punto para indicar el valor de la propiedad adjunta. Las instancias de clase
Inventor
, pupin
y tesla
, se han completado con datos. Para movernos "hacia
abajo" a través del gráfico de objetos y obtener el año de nacimiento de Tesla y la ciudad de nacimiento de Pupin,
usamos las siguientes expresiones:
// resulta ser 1856
int year = ( Integer) parser.parseExpression("birthdate.year + 1900").getValue(context);
String city = (String) parser.parseExpression("placeOfBirth.city").getValue(context);
// resulta ser 1856
val year = parser.parseExpression("birthdate.year + 1900").getValue(context) as Int
val city = parser.parseExpression("placeOfBirth.city").getValue(context) as String
Se permite no distinguir entre mayúsculas y minúsculas para la primera
letra de los nombres de propiedades. Entonces, las expresiones en el ejemplo anterior se pueden escribir como Fecha
de Birthdate.Year + 1900
y Lugar de PlaceOfBirth.City
, respectivamente. Además, se puede
acceder a las propiedades mediante llamadas a métodos, por ejemplo, getPlaceOfBirth().getCity()
en
lugar de placeOfBirth.city
.
El contenido de matrices y listas se puede obtener usando notación entre corchetes, como se muestra en el siguiente ejemplo:
ExpressionParser parser = new SpelExpressionParser();
EvaluationContext context = SimpleEvaluationContext.forReadOnlyDataBinding().build();
// Matriz de invenciones
// tiene el valor "Motor de inducción"
String invention = parser.parseExpression("inventions[3]").getValue(
context, tesla, String.class);
// Lista de miembros
// tiene el valor "Nikola Tesla".
String name = parser.parseExpression("members[0].name").getValue(
context, ieee, String.class);
// Lista de miembros
// tiene el valor "Comunicación inalámbrica"
String invention = parser.parseExpression("members[0].inventions[6]").getValue(
context, ieee, String.class);
val parser = SpelExpressionParser()
val context = SimpleEvaluationContext.forReadOnlyDataBinding().build()
// Conjunto de inventos
// importa "Motor de inducción"
val invention = parser.parseExpression("inventions[3]").getValue(
context, tesla, String::class.java)
// Lista de miembros
// tiene el valor "Nikola Tesla".
val name = parser.parseExpression("members[0].name").getValue(
context, ieee, String::class.java)
// Lista de miembros
// tiene el valor "Comunicación inalámbrica"
val invention = parser.parseExpression(" members[0].inventions[6]").getValue(
context, ieee, String::class.java)
El contenido de Las matrices se pueden obtener especificando el valor literal de la clave entre paréntesis. En
el siguiente ejemplo, dado que las claves para la matriz asociativa officers
son cadenas, podemos
especificar cadenas literales:
// Diccionario del oficial
Inventor pupin = parser.parseExpression("officers['president']").getValue(
societyContext, Inventor.class);
// tiene el valor "Idvor"
String city = parser.parseExpression("officers['president'].placeOfBirth.city").getValue(
societyContext, String.class);
// configuración de valores
parser.parseExpression("officers['advisors'][0].placeOfBirth.country").setValue(
societyContext, "Croatia");
// Diccionario de oficiales
val pupin = parser.parseExpression("officers['president']").getValue(
societyContext, Inventor::class.java)
// tiene valor "Idvor"
val city = parser.parseExpression("officers['president'].placeOfBirth.city").getValue(
societyContext, String::class.java)
// configuración de valores
parser.parseExpression("officers['advisors'][0].placeOfBirth.country").setValue(
societyContext, "Croatia")
Listas integrables
Puedes expresar listas directamente en una expresión usando la notación
{}
.
// definido como una lista de Java que contiene cuatro números
List numbers = (List) parser.parseExpression("{1,2,3,4}").getValue(context);
List listOfLists = (List) parser.parseExpression("{{'a','b'},{'x','y'}}").getValue(context);
// definido como una lista Java que contiene cuatro números
val numbers = parser.parseExpression("{1,2,3,4}" ).getValue(context) as List<*>
val listOfLists = parser.parseExpression("{{'a','b'},{'x','y'}}").getValue(context) as List<*>
{}
en sí mismo significa una lista vacía. Por motivos de rendimiento, si la lista consta
enteramente de literales fijos, se crea una lista de constantes para representar la expresión (en lugar de construir
una nueva lista cada vez que se evalúa).
Mapas en línea
También puedes expresar Map directamente en
una expresión usando la notación {key:value}
. El siguiente ejemplo muestra cómo hacer esto:
// se define como un mapa de Java que contiene dos entradas
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);
// se define como un mapa de Java que contiene dos entradas
val inventorInfo = parser. parseExpression("{name:'Nikola',dob:'10-July-1856'}").getValue(context) as Map<*, *>
val mapOfMaps = parser.parseExpression("{name:{first:'Nikola',last:'Tesla'},dob:{day:10,month:'July',year:1856}}").getValue(context) as Map<*, *>
{:}
en sí mismo significa un mapa vacío. Por motivos de rendimiento, si el mapa en sí consta de
literales fijos u otras estructuras constantes anidadas (listas o mapas), se crea un mapa de constantes para
representar la expresión (en lugar de construir un nuevo mapa cada vez que se evalúa). No es necesario incluir las
claves del mapa entre comillas (a menos que la clave contenga un punto (.)). Los ejemplos anteriores no utilizan
comillas.
Construcción de matrices
Puede crear matrices utilizando la sintaxis familiar de Java, especificando opcionalmente un inicializador para que la matriz se complete durante la construcción. El siguiente ejemplo muestra cómo hacer esto:
int[] numbers1 = (int[]) parser.parseExpression("new int[4]").getValue(context);
// Matriz con inicializador
int[] numbers2 = (int[]) parser.parseExpression("new int[]{1,2,3}").getValue(context);
// Matriz multidimensional
int[][] numbers3 = (int[][]) parser.parseExpression("new int[4][5]").getValue(context);
val numbers1 = parser.parseExpression("new int[4]").getValue(context) as IntArray
// Matriz con inicializador
val numbers2 = parser.parseExpression("new int[]{1,2,3}").getValue(context) as IntArray
// Números de valor de matriz
val numbers3 = parser.parseExpression("new int[4][5]").getValue( context) as Array<IntArray>
Actualmente, no se puede especificar un inicializador al crear una matriz multidimensional.
Métodos
Puedes llamar a métodos usando la sintaxis típica de programación Java. También puedes llamar a métodos en literales. También se admiten argumentos variables. Los siguientes ejemplos muestran cómo llamar a métodos:
// Literal de cadena que tiene el valor "bc"
String bc = parser.parseExpression("'abc'. substring(1, 3)").getValue(String.class);
// resulta ser verdadero
boolean isMember = parser.parseExpression("isMember('Mihajlo Pupin')").getValue(
societyContext, Boolean.class);
// cadena literal que tiene el valor "bc"
val bc = parser.parseExpression("'abc'.substring(1, 3)").getValue(String::class. java)
// resulta ser cierto
val isMember = parser.parseExpression("isMember('Mihajlo Pupin')").getValue(
Operadores
El lenguaje de expresión Spring admite los siguientes tipos de operadores:
Operadores relacionales
Operadores lógicos
Operadores matemáticos
Operador de asignación
Operadores relacionales
Los operadores relacionales (igual, no igual, menor que, menor o igual, mayor que y mayor que mayor o igual) se admiten mediante la notación de operador estándar. La siguiente lista proporciona varios operadores de ejemplo:
// resulta ser verdadero
boolean trueValue = parser.parseExpression("2 == 2").getValue(Boolean. class);
// resulta ser falso
boolean falseValue = parser.parseExpression("2 < -5.0").getValue(Boolean.class);
// resulta ser verdadero
boolean trueValue = parser.parseExpression("'black' < 'block'").getValue(Boolean.class);
// resulta ser
val trueValue = parser.parseExpression("2 == 2").getValue(Boolean::class.java)
// resulta ser be false
val falseValue = parser.parseExpression( "2 < -5.0").getValue(Boolean::class.java)
// resulta ser verdadero
val trueValue = parser.parseExpression("'black' < 'block'").getValue(Boolean::class.java)
Comparaciones de "mayor que" y "menor que" con null
obedecen a una regla simple: null
se considera nada (NO es cero). Como consecuencia, cualquier otro
valor siempre es mayor que null(X > null
es siempre true
) y ningún otro valor es menor
que nada (X < ; null
siempre es false
).
Si prefieres las comparaciones numéricas, evita las comparaciones basadas en números null
y prefiere
las nulas. comparaciones basadas en (por ejemplo, X > 0
o X < 0
).
Además de los operadores relacionales estándar, SpEL admite el operador instanceof
y un operador matches
basado en expresiones regulares. La siguiente lista proporciona ejemplos de ambas opciones:
// resulta ser falso
boolean falseValue = parser.parseExpression(
"'xyz' instanceof T(Integer)").getValue(Boolean.class);
// resulta ser verdadero
boolean trueValue = parser.parseExpression(
"'5.00' matches '^-?\\d+(\\.\\d{2})?$'").getValue(Boolean.class);
// resulta ser falso
boolean falseValue = parser.parseExpression(
"'5.0067' matches '^-?\\d+(\\.\\d{2})?$'").getValue(Boolean.class);
// resulta ser falso
val falseValue = parser.parseExpression(
"'xyz' instanceof T(Integer)").getValue(Boolean::class.java)
// resulta ser verdadero
val trueValue = parser.parseExpression(
"'5.00' matches '^-?\\d+(\\.\\d{2})?$'").getValue(Boolean::class.java)
// resulta ser falso
val falseValue = parser.parseExpression(
"'5.0067' matches '^-?\\d+(\\.\\d{2})?$'").getValue (Boolean::class.java)
1 instanceof T(int)
resulta ser
false
y 1 instanceof T(Integer)
resulta ser true
, como se esperaba.
Cada operador de carácter también se puede especificar como un equivalente puramente literal. Esto evita problemas cuando los caracteres utilizados tienen un significado especial para el tipo de documento en el que está incrustada la expresión (por ejemplo, un documento XML). Los textos equivalentes son:
lt
(<
)gt
(>
)le
(<=
)ge
(>=
)eq
(==
)ne
(!=
)div
(/
)mod
(%
)not
(!
) .
Todos los operadores de texto no distinguen entre mayúsculas y minúsculas.
Operadores lógicos
SpEL admite los siguientes operadores lógicos:
y
(&&
)o
(||
)no
(!
)
El siguiente ejemplo muestra cómo utilizar operadores lógicos:
// -- AND --
// resulta ser falso
boolean falseValue = parser.parseExpression("true and false").getValue(Boolean.class);
// resulta ser verdadero
String expression = "isMember('Nikola Tesla') and isMember('Mihajlo Pupin')";
boolean trueValue = parser.parseExpression(expression).getValue(societyContext, Boolean.class);
// -- O --
// resulta ser verdadero
boolean trueValue = parser.parseExpression("true or false").getValue(Boolean.class);
// resulta ser verdadero
String expression = "isMember('Nikola Tesla') or isMember('Albert Einstein')";
boolean trueValue = parser.parseExpression(expression).getValue(societyContext, Boolean.class);
// -- NO --
// resulta ser falso
boolean falseValue = parser.parseExpression("!true").getValue(Boolean.class);
// -- Y y NO --
String expression = "isMember('Nikola Tesla') and !isMember('Mihajlo Pupin')";
boolean falseValue = parser.parseExpression(expression).getValue(societyContext, Boolean.class);
// -- AND --
// resulta ser falso
val falseValue = parser.parseExpression("true and false").getValue(Boolean::class.java)
// resulta ser verdadero
val expression = "isMember('Nikola Tesla') and isMember('Mihajlo Pupin')"
val trueValue = parser.parseExpression(expression).getValue(societyContext, Boolean::class.java)
// -- O --
// resulta ser verdadero
val trueValue = parser.parseExpression("true or false").getValue(Boolean::class.java)
// resulta ser verdadero
val expression = "isMember('Nikola Tesla') or isMember('Albert Einstein')"
val trueValue = parser.parseExpression(expression).getValue(societyContext, Boolean::class.java)
// -- NOT --
// resulta ser falso
val falseValue = parser.parseExpression("!true").getValue(Boolean::class.java)
// -- Y y NO --
val expression = "isMember('Nikola Tesla') and !isMember('Mihajlo Pupin')"
val falseValue = parser.parseExpression(expression).getValue(societyContext, Boolean::class.java)
Operadores matemáticos
El operador de suma (+
) puede ser Se utiliza tanto para números como para cadenas. Los
operadores de resta (-
), multiplicación (*
) y división (/
) solo se
pueden utilizar para números. También puede utilizar los operadores de resto (%
) y crecimiento
exponencial (^
) para números. Se aplica la prioridad de operador estándar. El siguiente ejemplo
muestra los operadores matemáticos utilizados:
// Suma
int two = parser.parseExpression("1 + 1").getValue(Integer.class); // 2
String testString = parser.parseExpression(
"'test' + ' ' + 'string'").getValue(String.class);// 'cadena de prueba'
// Resta
int four = parser.parseExpression("1 - -3").getValue(Integer.class); // 4
double d = parser.parseExpression("1000.00 - 1e4").getValue(Double.class); // -9000
Multiplicación
int six = parser.parseExpression("-2 * -3").getValue(Integer.class); // 6
double twentyFour = parser.parseExpression("2.0 * 3e0 * 4").getValue(Double.class); // 24.0
//División
int minusTwo = parser.parseExpression("6 / -3").getValue(Integer.class); // -2
double one = parser.parseExpression("8.0 / 4e0 / 2").getValue(Double.class); // 1.0
// Tomando el resto
int three = parser.parseExpression("7 % 4").getValue(Integer.class); // 3
int one = parser.parseExpression("8 / 5 % 2").getValue(Integer.class); // 1
// Precedencia del operador
int minusTwentyOne = parser.parseExpression("1+2-3*8").getValue(Integer.class); // -21
// Valor de suma
val two = parser.parseExpression("1 + 1" ).getValue(Int::class.java) // 2
val testString = parser.parseExpression(
"'test' + ' ' + 'string'").getValue(String::class.java) // 'cadena de prueba'
// Resta
val four = parser.parseExpression("1 - -3").getValue(Int::class.java) // 4
val d = parser.parseExpression("1000.00 - 1e4").getValue(Double::class .java) // -9000
// Multiplicación
val six = parser.parseExpression("-2 * -3").getValue(Int::class.java) // 6
val twentyFour = parser.parseExpression("2.0 * 3e0 * 4").getValue(Double::class.java) // 24.0
// División
val minusTwo = parser.parseExpression("6 / -3").getValue(Int::class.java) // -2
val one = parser.parseExpression("8.0 / 4e0 / 2").getValue(Double::class.java) // 1.0
// Tomando el valor
val three = parser.parseExpression("7 % 4").getValue(Int::class. java) // 3
val one = parser.parseExpression("8 / 5 % 2").getValue(Int::class.java) // 1
// Precedencia del operador
val minusTwentyOne = parser.parseExpression("1+2-3 *8").getValue(Int::class.java) // -21
Operador de asignación
Para establecer un propiedad, utilice el operador de asignación
(=
). Esto generalmente se hace dentro de una llamada setValue
, pero también se puede hacer
dentro de una llamada getValue
. La siguiente lista muestra ambas formas de utilizar el operador de
asignación:
Inventor inventor = new Inventor();
EvaluationContext context = SimpleEvaluationContext.forReadWriteDataBinding().build();
parser.parseExpression("name").setValue(context, inventor, "Aleksandar Seovic");
// alternativa a
String aleks = parser.parseExpression(
"name = 'Aleksandar Seovic' ").getValue(context, inventor, String.class);
val inventor = Inventor()
val context = SimpleEvaluationContext.forReadWriteDataBinding().build()
parser.parseExpression("name").setValue(context, inventor, "Aleksandar Seovic")
// alternativo
val aleks = parser.parseExpression(
"name = 'Aleksandar Seovic'").getValue(context, inventor, String::class.java)
Tipos
Puede utilizar el operador especial T
para especificar una instancia de java.lang.Class
(tipo). Los métodos estáticos también se llaman mediante este operador. StandardEvaluationContext
usa
TypeLocator
para buscar tipos, y StandardTypeLocator
(que puede ser reemplazado) está
diseñado para aprovechar paquete de java.lang
. Esto significa que las referencias T()
a
tipos del paquete java.lang
no necesitan estar completamente calificadas, pero todas las demás
referencias de tipos deben estar calificadas. El siguiente ejemplo muestra cómo utilizar el operador
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);
val dateClass = parser.parseExpression("T(java.util.Date)").getValue(Class::class.java)
val stringClass = parser.parseExpression("T(String)").getValue(Class::class.java)
val trueValue = parser.parseExpression(
"T(java.math.RoundingMode).CEILING < T(java.math.RoundingMode ).FLOOR")
.getValue(Boolean::class.java)
Constructores
Puedes llamar a constructores usando el operador new
. Debe utilizar el nombre de clase completo
para todos los tipos excepto aquellos en el paquete java.lang(Integer
, Float
,
String
,
etc. Más). El siguiente ejemplo muestra cómo utilizar el operador new
para llamar a constructores:
Inventor einstein = p.parseExpression(
"new org. spring.samples.spel.inventor.Inventor('Albert Einstein', 'German')")
.getValue(Inventor.class);
// crea una nueva instancia de Inventor en el método add() Lista
p.parseExpression(
"Members.add(new org.spring.samples.spel.inventor.Inventor(
'Albert Einstein', 'German'))").getValue(societyContext );
val einstein = p.parseExpression(
"new org.spring.samples.spel.inventor.Inventor('Albert Einstein', 'German')")
.getValue(Inventor::class.java)
// crea una nueva instancia de Inventor en el método add() List
p.parseExpression(
"Members.add(new org.spring .samples.spel.inventor.Inventor('Albert Einstein', 'German'))")
.getValue(societyContext)
Variables
Puede hacer referencia a variables en una expresión usando la sintaxis
#variableName
. Las variables se establecen usando el método setVariable
en la
implementación EvaluationContext
.
Válido Los nombres de las variables deben constar de uno o más de los siguientes caracteres admitidos.
letras:
A
aZ
ya
az
números: de
0
a9
guión bajo:
_
signo de dólar:
$
El siguiente ejemplo muestra cómo utilizar 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"
val tesla = Inventor("Nikola Tesla", "Serbian")
val context = SimpleEvaluationContext.forReadWriteDataBinding().build()
context.setVariable("newName", "Mike Tesla")
parser.parseExpression("name = #newName").getValue(context, tesla)
println(tesla.name) // "Mike Tesla
Variables #this
y #root
La variable #this
siempre está
definida y se refiere al objeto de cálculo actual (en relación con el cual se resuelven las referencias no
calificadas). La variable #root
siempre está definida y hace referencia al objeto de contexto raíz.
Aunque #this
puede cambiar a medida que se evalúan los componentes de la expresión, #root
siempre se refiere a la raíz. Los siguientes ejemplos muestran cómo utilizar las variables #this
y
#root
:
// create array of integers
List<Integer> primes = new ArrayList<Integer>();
primes.addAll(Arrays.asList(2,3,5,7,11,13,17));
// create a parser and set the "primes" variable as an array of integers
ExpressionParser parser = new SpelExpressionParser();
EvaluationContext context = SimpleEvaluationContext.forReadOnlyDataAccess();
context.setVariable("primes", primes);
// all prime numbers > 10 from the list (using selection ?{...})
// turns out to be [11, 13, 17]
List<Integer> primesGreaterThanTen = (List<Integer>) parser.parseExpression(
"#primes.?[#this>10]").getValue(context);
// create an array of integers
val primes = ArrayList<Int>() primes.addAll(listOf(2, 3, 5, 7, 11, 13, 17))
// create a parser and set the variable "primes" as an array of integers
val parser = SpelExpressionParser()
val context = SimpleEvaluationContext.forReadOnlyDataAccess()
context.setVariable("primes", primes)
// all primes > 10 from the list (using selection ?{...})
// turns out to be [11, 13, 17]
val primesGreaterThanTen = parser.parseExpression(
"#primes.?[#this>10]").getValue(context) as List< ;Int>
Funciones
Puede ampliar SpEL registrando funciones definidas por el usuario que se pueden llamar en
el línea de expresión. La función se registra a través de EvaluationContext
. El siguiente ejemplo
muestra cómo registrar una función definida por el usuario:
Method method = ...;
EvaluationContext context = SimpleEvaluationContext.forReadOnlyDataBinding().build();
context.setVariable("myFunction", method);
val method: Method = ...
val context = SimpleEvaluationContext.forReadOnlyDataBinding().build()
context.setVariable("myFunction", method)
Por ejemplo, considere el siguiente método de utilidad que invierte la línea:
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();
}
}
fun reverseString(input: String): String {
val backwards = StringBuilder(input.length)
for (i in 0 until input.length) {
backwards.append(input[input.length - 1 - i])
}
return backwards.toString()
}
Luego puede registrarse y utilizar el método anterior, como se muestra en el siguiente ejemplo:
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);
val parser = SpelExpressionParser()
val context = SimpleEvaluationContext.forReadOnlyDataBinding().build()
context.setVariable("reverseString", ::reverseString::javaMethod)
val helloWorldReversed = parser.parseExpression(
"#reverseString('hello')").getValue(context, String::class.java)
Referencias de Bean
Si Si el contexto de evaluación se ha configurado con un solucionador de beans,
podrá buscar beans en una expresión utilizando el símbolo @
. El siguiente ejemplo muestra cómo hacer
esto:
ExpressionParser parser = new SpelExpressionParser();
StandardEvaluationContext context = new StandardEvaluationContext();
context.setBeanResolver(new MyBeanResolver());
// Esto hará que se llame a resolve(context, "something") en MyBeanResolver durante la evaluación
Object bean = parser.parseExpression("@something").getValue(context);
val parser = SpelExpressionParser()
val context = StandardEvaluationContext()
context.setBeanResolver(MyBeanResolver())
// Esto llamará a resolve(context, " algo ") para MyBeanResolver durante la evaluación
val bean = parser.parseExpression("@something").getValue(context)
Para acceder al bean en sí - fábrica, debe reemplazar el nombre del bean con el símbolo
&
. El siguiente ejemplo muestra cómo hacer esto:
ExpressionParser parser = new SpelExpressionParser();
StandardEvaluationContext context = new StandardEvaluationContext();
context.setBeanResolver(new MyBeanResolver());
// Esto hará que se llame a resolve(context,"&foo") en MyBeanResolver durante la evaluación
Object bean = parser.parseExpression("&foo").getValue(context);
val parser = SpelExpressionParser()
val context = StandardEvaluationContext()
context.setBeanResolver(MyBeanResolver())
// Esto llamará a resolve(contexto) ,"&foo") para MyBeanResolver durante la evaluación
val bean = parser.parseExpression("&foo").getValue(context)
Ternario ( Operador If-Then-Else)
Puede utilizar el operador ternario para realizar una lógica de salto condicional if-then-else dentro de una expresión. El siguiente listado muestra un ejemplo sencillo:
String falseString = parser.parseExpression(
"false ? 'trueExp' : 'falseExp'").getValue(String.class);
val falseString = parser.parseExpression(
"false ? 'trueExp' : 'falseExp'").getValue(String::class.java)
En este caso, el booleano false
da como resultado devolviendo el valor de cadena
'falseExp'
. El siguiente es un ejemplo más cercano a la práctica:
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 es miembro de la Sociedad IEEE"
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'"
val queryResultString = parser.parseExpression(expression)
.getValue(societyContext, String::class.java)
// queryResultString = "Nikola Tesla es miembro de la Sociedad IEEE"
Ver. Consulte la siguiente sección sobre el operador de Elvis para obtener una sintaxis de operador ternario aún más breve.
Operador de Elvis
El operador de Elvis es una abreviatura de la sintaxis del operador ternario y se utiliza en el lenguaje Groovy. Cuando se utiliza la sintaxis del operador ternario, normalmente es necesario repetir la variable dos veces, como se muestra en el siguiente ejemplo:
String name = "Elvis Presley";
String displayName = (name != null ? name : "Unknown");
Puedes usar el operador Elvis en su lugar (llamado así debido a la similitud con El cabello de Elvis Presley). El siguiente ejemplo muestra cómo utilizar el operador de Elvis:
ExpressionParser parser = new SpelExpressionParser();
String name = parser.parseExpression("name?:'Unknown'").getValue(new Inventor(), String.class);
System.out.println(name); // 'Desconocido'
val parser = SpelExpressionParser()
val name = parser.parseExpression("name?:'Unknown'").getValue(Inventor(), String::class.java)
println(name) // 'Desconocido'
El siguiente listado muestra un ejemplo más complejo:
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
val parser = SpelExpressionParser()
val context = SimpleEvaluationContext.forReadOnlyDataBinding().build()
val tesla = Inventor("Nikola Tesla", "Serbian")
var name = parser.parseExpression("name?:'Elvis Presley'").getValue(context, tesla, String::class.java)
println(name) // Nikola Tesla
tesla.setName(null)
name = parser.parseExpression("name?:'Elvis Presley'").getValue(context, tesla, String::class.java)
println(name) // Elvis Presley
Puede utilizar el operador de Elvis para aplicar valores predeterminados
en las expresiones. El siguiente ejemplo muestra cómo utilizar el operador de Elvis en una expresión anotada con
@Value
:
@Value("#{systemProperties['pop3.port'] ?: 25}")
Esto inyecta la propiedad del sistema pop3.port
si está definida, o 25 si no.
Operador de navegación segura
El operador de navegación segura se utiliza para evitar
NullPointerException
y proviene del lenguaje
Maravilloso. Normalmente, si tiene una referencia a un objeto, es posible que desee asegurarse de que no
esté vacía antes de acceder a los métodos o propiedades del objeto. Para evitar esto, el operador de navegación
segura devuelve nulo en lugar de generar una excepción. El siguiente ejemplo muestra cómo utilizar el operador de
navegación segura:
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); // nulo - ¡¡¡no arroja NullPointerException!!!
val parser = SpelExpressionParser()
val context = SimpleEvaluationContext.forReadOnlyDataBinding().build()
val tesla = Inventor("Nikola Tesla", "Serbian")
tesla.setPlaceOfBirth(PlaceOfBirth("Smiljan"))
var city = parser.parseExpression("placeOfBirth?.city").getValue(context, tesla, String::class.java)
println(city) // Smiljan
tesla.setPlaceOfBirth(null)
city = parser.parseExpression("placeOfBirth?.city").getValue(context, tesla, String::class.java)
println(city) // null - ¡¡¡no arroja NullPointerException!!!
Selección de colecciones
La selección es A potente característica de lenguaje de expresión que le permite transformar una colección de origen en otra colección seleccionando entre sus registros.
La selección utiliza la sintaxis .?[selectionExpression]
. Filtra la colección y devuelve una nueva
colección que contiene un subconjunto de los elementos originales. Por ejemplo, utilizando el muestreo, puede
obtener fácilmente una lista de inventores serbios, como se muestra en el siguiente ejemplo:
List<Inventor> list = (List<Inventor>) parser.parseExpression(
"members.?[nationality == 'Serbian']").getValue(societyContext);
val list = parser.parseExpression(
"members.?[nationality == 'Serbian']").getValue(societyContext) as List<Inventor>
El muestreo es compatible con matrices y cualquier cosa que implemente java.lang.Iterable
o java.util.Map
.
Para una lista o matriz, los criterios de selección se evalúan en cada elemento individual. Con respecto a una
matriz asociativa, los criterios de selección se evalúan en cada elemento de la matriz asociativa (objetos Java
de tipo Map.Entry
). Cada entrada de la matriz asociativa tiene una key
y un
value
,
disponible como propiedades para usar al buscar.
La siguiente expresión devuelve una nueva matriz asociativa que consta de aquellos elementos de la matriz asociativa original en los que el valor del elemento es menor. que 27:
Map newMap = parser.parseExpression("map.?[value<27]").getValue();
val newMap = parser.parseExpression("map.?[value<27]").getValue()
Además de devolver todos los elementos seleccionados, solo puede devolver el primer o el último elemento. Para
obtener el primer elemento que coincida con los criterios de selección, la sintaxis es
.^[selectionExpression]
.
Para obtener el último elemento que coincida con los criterios de selección, la sintaxis es .$[selectionExpression]
.
Proyección de colecciones
Proyección permite que una colección controle la evaluación de una subexpresión y el resultado es una nueva
colección. La sintaxis para la proyección es .![projectionExpression]
. Por ejemplo, digamos que
tenemos una lista de inventores, pero queremos una lista de las ciudades en las que nacieron. Básicamente,
queremos calcular 'placeOfBirth.city' para cada entrada en la lista de inventores. El siguiente ejemplo utiliza
una proyección para hacer esto:
// devuelve ['Smiljan', 'Idvor' ].
List placesOfBirth = (List)parser.parseExpression("members.![placeOfBirth.city]");
// devuelve ['Smiljan', 'Idvor' ].
val placesOfBirth = parser.parseExpression("members.![placeOfBirth.city]") as List<*>
La proyección es compatible con matrices y cualquier cosa que implemente java.lang.Iterable
o java.util.Map
.
Cuando utiliza una matriz asociativa para controlar una proyección, la expresión de la proyección se evalúa
sobre cada entrada en esa matriz asociativa (representada como Map.Entry
en Java). El resultado de
una proyección sobre una matriz asociativa es una lista que consiste en evaluar la expresión de proyección para
cada entrada en la matriz asociativa.
Plantillas de expresión
Las plantillas de expresión le permiten mezclar texto literal con uno o más bloques de cálculos. Cada bloque de
cálculos está delimitado por caracteres de prefijo y sufijo que puede definir. Normalmente, #{ }
se
utilizan como delimitadores, como se muestra en el siguiente ejemplo:
String randomPhrase = parser.parseExpression(
"random number is #{T(java.lang.Math).random()}",
new TemplateParserContext()).getValue(String.class);
// resulta "el número aleatorio es 0.7038186818312008"
val randomPhrase = parser.parseExpression(
"random number is #{T(java.lang.Math).random()}",
TemplateParserContext()).getValue(String::class.java)
// resulta "el número aleatorio es 0.7038186818312008"
La cadena se calcula concatenando el texto literal 'random number is'
con el resultado de
calcular la expresión dentro del delimitador #{ }
(en este caso, el resultado de llamar al random()
).
El segundo argumento del método parseExpression()
es de tipo ParserContext
. La
interfaz ParserContext
se utiliza para influir en cómo se analiza una expresión para proporcionar
funcionalidad de creación de plantillas de expresión. La siguiente es la definición de
TemplateParserContext
:
public class TemplateParserContext implements ParserContext {
public String getExpressionPrefix() {
return "#{";
}
public String getExpressionSuffix() {
return "}";
}
public boolean isTemplate() {
return true;
}
}
class TemplateParserContext : ParserContext {
override fun getExpressionPrefix(): String {
return "#{"
}
override fun getExpressionSuffix(): String {
return "}"
}
override fun isTemplate(): Boolean {
return true
}
}