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.

Java

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

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:

Java

// resulta ser 1856
int year = ( Integer) parser.parseExpression("birthdate.year + 1900").getValue(context);
            String city = (String) parser.parseExpression("placeOfBirth.city").getValue(context);
Kotlin
 
// 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:

Java

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

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:

Java

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

// 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 {}.

Java

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

// 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:

Java

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

// 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:

Java

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

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:

Java

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

// 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:

Java

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

// 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:

Java

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

// 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)
Tenga cuidado con los tipos primitivos porque están empaquetados en sus propios tipos de contenedor. Por ejemplo, 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:

Java

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

// -- 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:

Java

// 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
Kotlin

// 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:

Java

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

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:

Java

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

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:

Java

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

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 a Z y a a z

  • números: de 0 a 9

  • guión bajo: _

  • signo de dólar: $

El siguiente ejemplo muestra cómo utilizar variables.

Java

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"
Kotlin

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:

Java

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

// 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:

Java

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

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:

Java

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();
    }
}
Kotlin

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:

Java

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

Java

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

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:

Java

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

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:

Java

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

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:

Java

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"
Kotlin

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:

Java

ExpressionParser parser = new SpelExpressionParser();
String name = parser.parseExpression("name?:'Unknown'").getValue(new Inventor(), String.class);
System.out.println(name);  // 'Desconocido'
Kotlin

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:

Java

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
Kotlin

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:

Java

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!!!
Kotlin

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:

Java

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

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:

Java
Map newMap = parser.parseExpression("map.?[value<27]").getValue();
Kotlin
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:

Java
// devuelve ['Smiljan', 'Idvor' ].
List placesOfBirth = (List)parser.parseExpression("members.![placeOfBirth.city]");
Kotlin
// 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:

Java
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"
Kotlin
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:

Java
public class TemplateParserContext implements ParserContext {
    public String getExpressionPrefix() {
        return "#{";
    }
    public String getExpressionSuffix() {
        return "}";
    }
    public boolean isTemplate() {
        return true;
    }
}
Kotlin
class TemplateParserContext : ParserContext {
    override fun getExpressionPrefix(): String {
        return "#{"
    }
    override fun getExpressionSuffix(): String {
        return "}"
    }
    override fun isTemplate(): Boolean {
        return true
    }
}