20210429 SpEL表达式
主要接口:
org.springframework.expression.Expression
org.springframework.expression.ExpressionParser
org.springframework.expression.EvaluationContext
org.springframework.expression.ParserContext
org.springframework.expression.spel.SpelParserConfiguration
用法说明
创建 SpEL 解析器:
ExpressionParser parser = new SpelExpressionParser();
场景
Company
内有 Person
, Person
内有 BirthPlace
@Data
public class Company {
private String companyName;
private List<Person> personList;
private Map<String, Person> deptCodeLeaderMap;
public boolean isMember(String name) {
for (Person person : personList) {
if (Objects.equals(name, person.getName())) {
return true;
}
}
return false;
}
}
@NoArgsConstructor
@Data
public class Person {
private String name;
private Integer age;
private Date birthday;
private BirthPlace birthPlace;
private String[] books;
public Person(String name, Integer age) {
this.name = name;
this.age = age;
}
public boolean hasBook(String book) {
for (String item : books) {
if (Objects.equals(item, book)) {
return true;
}
}
return false;
}
}
@Data
public class BirthPlace {
private String city;
private String country;
}
字面值(Literal expressions)
@Test
public void testLiteralExpressions() {
// 字符串
String helloWorld = (String) parser.parseExpression("'Hello World'").getValue(); // Hello World
// double
double d = (double) parser.parseExpression("1.234").getValue(); // 1.234
// double,科学计数法
double avogadrosNumber = (Double) parser.parseExpression("6.0221415E+23").getValue(); // 6.0221415E23
// 16 进制
int maxValue = (Integer) parser.parseExpression("0x7FFFFFFF").getValue(); // 2147483647
// 布尔值
boolean trueValue = (Boolean) parser.parseExpression("true").getValue(); // true
// NULL
Object nullValue = parser.parseExpression("null").getValue(); // null
}
Properties, Arrays, Lists, Maps, and Indexers
类属性(Properties)
@Test
public void testProperties() {
int year = (Integer) parser.parseExpression("birthday.year + 1900").getValue(person); // 2012
String city = (String) parser.parseExpression("birthPlace.city").getValue(person); // city0
}
列表(ArrayList)
@Test
public void testArrayList() {
context = SimpleEvaluationContext.forReadOnlyDataBinding().build();
String book2 = parser.parseExpression("books[2]").getValue(context, person, String.class); // book2
String person0Name = parser.parseExpression("personList[0].name").getValue(context, company, String.class); // person0
String person0Book2 = parser.parseExpression("personList[0].books[1]").getValue(context, company, String.class); // book1
// parser.parseExpression("deptCodeLeaderMap['dept1'].birthPlace.country").setValue(context, company, "country0xx"); // org.springframework.expression.spel.SpelEvaluationException: EL1010E: Property or field 'country' cannot be set on object of type 'study.spel.bean.BirthPlace' - maybe not public or not writable?
}
映射(Map)
@Test
public void testMap() {
Person dept0Leader = parser.parseExpression("deptCodeLeaderMap['dept0']").getValue(company, Person.class); // Person(name=person0 ...
String city = parser.parseExpression("deptCodeLeaderMap['dept0'].birthPlace.city").getValue(company, String.class); // city0
// 设置值
parser.parseExpression("deptCodeLeaderMap['dept1'].birthPlace.country").setValue(company, "country0xx");
String dept1Country = parser.parseExpression("deptCodeLeaderMap['dept1'].birthPlace.country").getValue(company, String.class); // country0xx
}
内联列表(Inline Lists)
@Test
public void testInlineLists() {
context = SimpleEvaluationContext.forReadOnlyDataBinding().build();
// evaluates to a Java list containing the four numbers
List numbers = (List) parser.parseExpression("{1,2,3,4}").getValue(context); // [1, 2, 3, 4]
List listOfLists = (List) parser.parseExpression("{{'a','b'},{'x','y'}}").getValue(context); // [[a, b], [x, y]]
}
内联映射(Inline Maps)
@Test
public void testInlineMaps() {
context = SimpleEvaluationContext.forReadOnlyDataBinding().build();
// 单层
Map inventorInfo = (Map) parser.parseExpression("{name:'Nikola',dob:'10-July-1856'}").getValue(context); // {name=Nikola, dob=10-July-1856}
// 多层嵌套
Map mapOfMaps = (Map) parser.parseExpression("{name:{first:'Nikola',last:'Tesla'},dob:{day:10,month:'July',year:1856}}").getValue(context); // {name={first=Nikola, last=Tesla}, dob={day=10, month=July, year=1856}}
}
数组构造器(Array Construction)
@Test
public void testArrayConstruction() {
context = SimpleEvaluationContext.forReadOnlyDataBinding().build();
int[] numbers1 = (int[]) parser.parseExpression("new int[4]").getValue(context); // [0, 0, 0, 0]
// Array with initializer
int[] numbers2 = (int[]) parser.parseExpression("new int[]{1,2,3}").getValue(context); // [1, 2, 3]
// Multi dimensional array
int[][] numbers3 = (int[][]) parser.parseExpression("new int[4][5]").getValue(context); // [[0, 0, 0, 0, 0], [0, 0, 0, 0, 0], [0, 0, 0, 0, 0], [0, 0, 0, 0, 0]]
}
实例方法(Methods)
@Test
public void testMethods() {
String bc = parser.parseExpression("'abc'.substring(1, 3)").getValue(String.class); // bc
boolean hasBook = parser.parseExpression("hasBook('book0')").getValue(person, Boolean.class); // true
}
运算符(Operators)
关系运算符(Relational Operators)
/**
* Operators - Relational Operators
*
* lt(<)
* gt(>)
* le(<=)
* ge(>=)
* eq(==)
* ne(!=)
* div(/)
* mod(%)
* not(!)
*/
@Test
public void testOperatorsRelationalOperators() {
boolean trueValue = parser.parseExpression("2 == 2").getValue(Boolean.class);
boolean trueValueEq = parser.parseExpression("2 eq 2").getValue(Boolean.class);
boolean falseValue = parser.parseExpression("2 < -5.0").getValue(Boolean.class);
boolean trueValue2 = parser.parseExpression("'black' < 'block'").getValue(Boolean.class);
// ----------------------------------------------------------------- //
boolean falseValue2 = parser.parseExpression("'xyz' instanceof T(Integer)").getValue(Boolean.class);
boolean trueValue3 = parser.parseExpression("'5.00' matches '^-?\\d+(\\.\\d{2})?$'").getValue(Boolean.class);
boolean falseValue3 = parser.parseExpression("'5.0067' matches '^-?\\d+(\\.\\d{2})?$'").getValue(Boolean.class);
}
逻辑运算符(Logical Operators)
/**
* Operators - Logical Operators
*
* and (&&)
* or (||)
* not (!)
*/
@Test
public void testOperatorsLogicalOperators() {
// -- AND -- //
boolean falseValue = parser.parseExpression("true and false").getValue(Boolean.class);
String expression = "isMember('person0') and isMember('person1')";
boolean trueValue = parser.parseExpression(expression).getValue(company, Boolean.class);
// -- OR -- //
boolean trueValue2 = parser.parseExpression("true or false").getValue(Boolean.class);
expression = "isMember('person0') or isMember('person1')";
boolean trueValue3 = parser.parseExpression(expression).getValue(company, Boolean.class);
// -- NOT -- //
boolean falseValue2 = parser.parseExpression("!true").getValue(Boolean.class);
// -- AND and NOT -- //
expression = "isMember('Nikola Tesla') and !isMember('Mihajlo Pupin')";
boolean falseValue3 = parser.parseExpression(expression).getValue(company, Boolean.class);
}
数学运算符(Mathematical Operators)
@Test
public void testMathematicalOperators() {
// 加法
int two = parser.parseExpression("1 + 1").getValue(Integer.class); // 2
// 字符串拼接
String testString = parser.parseExpression("'test' + ' ' + 'string'").getValue(String.class); // 'test string'
// 减法
int four = parser.parseExpression("1 - -3").getValue(Integer.class); // 4
double d = parser.parseExpression("1000.00 - 1e4").getValue(Double.class); // -9000
// 乘法
int six = parser.parseExpression("-2 * -3").getValue(Integer.class); // 6
double twentyFour = parser.parseExpression("2.0 * 3e0 * 4").getValue(Double.class); // 24.0
// 除法
int minusTwo = parser.parseExpression("6 / -3").getValue(Integer.class); // -2
double one = parser.parseExpression("8.0 / 4e0 / 2").getValue(Double.class); // 1.0
// 取模
int three = parser.parseExpression("7 % 4").getValue(Integer.class); // 3
int one1 = parser.parseExpression("8 / 5 % 2").getValue(Integer.class); // 1
// 运算符优先级
int minusTwentyOne = parser.parseExpression("1+2-3*8").getValue(Integer.class); // -21
}
赋值运算符(The Assignment Operator)
/**
* Operators - The Assignment Operator
*/
@Test
public void testOperatorsAssignment() {
context = SimpleEvaluationContext.forReadWriteDataBinding().build();
// 会设置 person 的 name 属性为 Aleksandar Seovic
// parser.parseExpression("name").setValue(context, person, "Aleksandar Seovic");
// 会设置 person 的 name 属性为 Aleksandar Seovic
String aleks = parser.parseExpression("name = 'Aleksandar Seovic'").getValue(context, person, String.class);
}
类(Types)
@Test
public void testTypes() {
Class dateClass = parser.parseExpression("T(java.util.Date)").getValue(Class.class); // class java.util.Date
Class stringClass = parser.parseExpression("T(String)").getValue(Class.class); // class java.lang.String
boolean trueValue = parser.parseExpression("T(java.math.RoundingMode).CEILING < T(java.math.RoundingMode).FLOOR").getValue(Boolean.class); // true
}
构造器(Constructors)
@Test
public void testConstructors() {
// 通过构造器创建 Person 实例
Person einstein = parser.parseExpression("new study.spel.bean.Person('Albert Einstein', 20)").getValue(Person.class);
// 调用 company 的 personList 的 add 方法,并加入新建 person
parser.parseExpression("PersonList.add(new study.spel.bean.Person('Albert Einstein', 20))").getValue(company);
}
变量(Variables)
/**
* Variables
*
* 有效的变量名称必须由以下一个或多个受支持的字符组成:
* letters: A to Z and a to z
* digits: 0 to 9
* underscore: _
* dollar sign: $
*/
@Test
public void testVariables() {
context = SimpleEvaluationContext.forReadWriteDataBinding().build();
// 设置变量
context.setVariable("newName", "Mike Tesla");
// 通过 #variableName 使用变量
parser.parseExpression("name = #newName").getValue(context, person);
System.out.println(person.getName()); // "Mike Tesla"
}
#this
和 #root
@Test
public void testVariablesThisRoot() {
context = SimpleEvaluationContext.forReadOnlyDataBinding().build();
List<Integer> primes = new ArrayList();
primes.addAll(Arrays.asList(2, 3, 5, 7, 11, 13, 17));
context.setVariable("primes", primes);
// 筛选 List 中大于 10 的
// [11, 13, 17]
List<Integer> primesGreaterThanTen = (List<Integer>) parser.parseExpression("#primes.?[#this>10]").getValue(context);
}
函数(Functions)
@Test
public void testFunctions() throws NoSuchMethodException {
context = SimpleEvaluationContext.forReadOnlyDataBinding().build();
// 设置函数变量
context.setVariable("parseInt", Integer.class.getDeclaredMethod("parseInt", String.class));
// 使用函数变量,转为整型 100
Integer parseInt = parser.parseExpression("#parseInt('100')").getValue(context, Integer.class);
}
Bean 引用(Bean References)
@Test
public void testBeanReferences() {
StandardEvaluationContext context = new StandardEvaluationContext();
context.setBeanResolver(new MyBeanResolver());
// 获取 Bean
// 会调用 org.spring.samples.spel.inventor.MyBeanResolver.resolve
Object bean = parser.parseExpression("@something").getValue(context);
// 获取 Bean 工厂
Object bean2 = parser.parseExpression("&foo").getValue(context);
}
三元运算符(Ternary Operator)
@Test
public void testTernaryOperator() {
context = SimpleEvaluationContext.forReadWriteDataBinding().withMethodResolvers(DataBindingMethodResolver.forInstanceMethodInvocation()).build();
context.setVariable("queryName", "person0");
parser.parseExpression("companyName").setValue(context, company, "IEEE");
String expression = "isMember(#queryName)? #queryName + ' is a member of the ' " + "+ companyName + ' Society' : #queryName + ' is not a member of the ' + companyName + ' Society'";
String queryResultString = parser.parseExpression(expression).getValue(context, company, String.class); // person0 is a member of the IEEE Society
}
Elvis 运算符(The Elvis Operator)
@Test
public void testElvisOperator() {
context = SimpleEvaluationContext.forReadOnlyDataBinding().build();
String name1 = parser.parseExpression("name?:'Unknown'").getValue(new Person(), String.class); // 'Unknown'
String name2 = parser.parseExpression("name?:'Elvis Presley'").getValue(context, person, String.class); // person0
person.setName(null);
String name3 = parser.parseExpression("name?:'Elvis Presley'").getValue(context, person, String.class); // Elvis Presley
}
空安全导航操作符(Safe Navigation Operator)
/**
* Safe Navigation Operator
*
* 避免空指针异常
*/
@Test
public void testSafeNavigationOperator() {
context = SimpleEvaluationContext.forReadOnlyDataBinding().build();
// city0
String city1 = parser.parseExpression("birthPlace?.city").getValue(context, person, String.class);
person.setBirthPlace(null);
String city2 = parser.parseExpression("birthPlace?.city").getValue(context, person, String.class); // null
String city3 = parser.parseExpression("birthPlace.city").getValue(context, person, String.class); // 抛出异常:SpelEvaluationException
}
集合选择(Collection Selection)
@Test
public void testCollectionSelection() {
List<Person> list = (List<Person>) parser.parseExpression("personList.?[birthPlace.city == 'city0']").getValue(company);
/*
* map.?[value<27] 输入值小于27
* .^[selectionExpression] 获得与所选内容匹配的第一个条目
* .$[selectionExpression] 获得与所选内容匹配的最后一个条目
*/
}
集合投影(Collection Projection)
@Test
public void testCollectionProjection() {
List placesOfBirth = (List) parser.parseExpression("personList.![birthPlace.city]").getValue(company); // [city0, city1]
}
表达式模板(Expression templating)
/**
* Expression templating
*/
@Test
public void testExpressionTemplating() {
String randomPhrase = parser.parseExpression("random number is #{T(java.lang.Math).random()}", new TemplateParserContext()).getValue(String.class); // random number is 0.22093794778910136
}
测试案例
项目依赖
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.2.9.RELEASE</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.20</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.13</version>
</dependency>
代码
所有测试代码
import org.junit.Before;
import org.junit.Test;
import org.spring.samples.spel.inventor.MyBeanResolver;
import org.springframework.expression.EvaluationContext;
import org.springframework.expression.ExpressionParser;
import org.springframework.expression.common.TemplateParserContext;
import org.springframework.expression.spel.standard.SpelExpressionParser;
import org.springframework.expression.spel.support.DataBindingMethodResolver;
import org.springframework.expression.spel.support.SimpleEvaluationContext;
import org.springframework.expression.spel.support.StandardEvaluationContext;
import study.spel.bean.BirthPlace;
import study.spel.bean.Company;
import study.spel.bean.Person;
import java.util.*;
public class Test3 {
ExpressionParser parser;
EvaluationContext context;
Company company;
Person person;
BirthPlace birthPlace;
@Before
public void before() {
parser = new SpelExpressionParser();
company = new Company();
person = new Person();
birthPlace = new BirthPlace();
birthPlace.setCity("city0");
birthPlace.setCountry("country0");
Calendar calendar = Calendar.getInstance();
calendar.set(2012, 11, 12); // 2012-12-12 , month 从 0 开始
// System.out.println(calendar.getTime()); // Wed Dec 12 09:52:23 CST 2012
person.setName("person0");
person.setBirthday(calendar.getTime());
person.setBirthPlace(birthPlace);
person.setBooks(new String[]{"book0", "book1", "book2"});
Person person2 = new Person();
person2.setName("person1");
BirthPlace birthPlace2 = new BirthPlace();
birthPlace2.setCity("city1");
birthPlace2.setCountry("country1");
Calendar calendar2 = Calendar.getInstance();
calendar2.set(2022, 11, 12); // 2012-12-12 , month 从 0 开始
person2.setName("person1");
person2.setBirthday(calendar2.getTime());
person2.setBirthPlace(birthPlace2);
person2.setBooks(new String[]{"book20", "book21", "book22"});
company.setCompanyName("company0");
List<Person> personList = new ArrayList<>();
personList.add(person);
personList.add(person2);
company.setPersonList(personList);
Map<String, Person> deptCodeLeaderMap = new HashMap<>();
deptCodeLeaderMap.put("dept0", person);
deptCodeLeaderMap.put("dept1", person2);
company.setDeptCodeLeaderMap(deptCodeLeaderMap);
}
// society - company
// Inventor - person
// placeOfBirth - birthPlace
// officers - deptCodeLeaderMap
/**
* Expression templating
*/
@Test
public void testExpressionTemplating() {
String randomPhrase = parser.parseExpression("random number is #{T(java.lang.Math).random()}", new TemplateParserContext()).getValue(String.class); // random number is 0.22093794778910136
}
/**
* Collection Projection
*/
@Test
public void testCollectionProjection() {
List placesOfBirth = (List) parser.parseExpression("personList.![birthPlace.city]").getValue(company); // [city0, city1]
}
/**
* Collection Selection
*/
@Test
public void testCollectionSelection() {
List<Person> list = (List<Person>) parser.parseExpression("personList.?[birthPlace.city == 'city0']").getValue(company);
/*
* map.?[value<27] 输入值小于27
* .^[selectionExpression] 获得与所选内容匹配的第一个条目
* .$[selectionExpression] 获得与所选内容匹配的最后一个条目
*/
}
/**
* Safe Navigation Operator
*
* 避免空指针异常
*/
@Test
public void testSafeNavigationOperator() {
context = SimpleEvaluationContext.forReadOnlyDataBinding().build();
// city0
String city1 = parser.parseExpression("birthPlace?.city").getValue(context, person, String.class);
person.setBirthPlace(null);
String city2 = parser.parseExpression("birthPlace?.city").getValue(context, person, String.class); // null
String city3 = parser.parseExpression("birthPlace.city").getValue(context, person, String.class); // 抛出异常:SpelEvaluationException
}
/**
* The Elvis Operator
*/
@Test
public void testElvisOperator() {
context = SimpleEvaluationContext.forReadOnlyDataBinding().build();
String name1 = parser.parseExpression("name?:'Unknown'").getValue(new Person(), String.class); // 'Unknown'
String name2 = parser.parseExpression("name?:'Elvis Presley'").getValue(context, person, String.class); // person0
person.setName(null);
String name3 = parser.parseExpression("name?:'Elvis Presley'").getValue(context, person, String.class); // Elvis Presley
}
/**
* Ternary Operator (If-Then-Else)
*/
@Test
public void testTernaryOperator() {
context = SimpleEvaluationContext.forReadWriteDataBinding().withMethodResolvers(DataBindingMethodResolver.forInstanceMethodInvocation()).build();
context.setVariable("queryName", "person0");
parser.parseExpression("companyName").setValue(context, company, "IEEE");
String expression = "isMember(#queryName)? #queryName + ' is a member of the ' " + "+ companyName + ' Society' : #queryName + ' is not a member of the ' + companyName + ' Society'";
String queryResultString = parser.parseExpression(expression).getValue(context, company, String.class); // person0 is a member of the IEEE Society
}
/**
* Bean References
*/
@Test
public void testBeanReferences() {
StandardEvaluationContext context = new StandardEvaluationContext();
context.setBeanResolver(new MyBeanResolver());
// 获取 Bean
// 会调用 org.spring.samples.spel.inventor.MyBeanResolver.resolve
Object bean = parser.parseExpression("@something").getValue(context);
// 获取 Bean 工厂
Object bean2 = parser.parseExpression("&foo").getValue(context);
}
/**
* Functions
*/
@Test
public void testFunctions() throws NoSuchMethodException {
context = SimpleEvaluationContext.forReadOnlyDataBinding().build();
// 设置函数变量
context.setVariable("parseInt", Integer.class.getDeclaredMethod("parseInt", String.class));
// 使用函数变量,转为整型 100
Integer parseInt = parser.parseExpression("#parseInt('100')").getValue(context, Integer.class);
}
/**
* Variables - The #this and #root Variables
*/
@Test
public void testVariablesThisRoot() {
context = SimpleEvaluationContext.forReadOnlyDataBinding().build();
List<Integer> primes = new ArrayList();
primes.addAll(Arrays.asList(2, 3, 5, 7, 11, 13, 17));
context.setVariable("primes", primes);
// 筛选 List 中大于 10 的
// [11, 13, 17]
List<Integer> primesGreaterThanTen = (List<Integer>) parser.parseExpression("#primes.?[#this>10]").getValue(context);
}
/**
* Variables
*
* 有效的变量名称必须由以下一个或多个受支持的字符组成:
* letters: A to Z and a to z
* digits: 0 to 9
* underscore: _
* dollar sign: $
*/
@Test
public void testVariables() {
context = SimpleEvaluationContext.forReadWriteDataBinding().build();
// 设置变量
context.setVariable("newName", "Mike Tesla");
// 通过 #variableName 使用变量
parser.parseExpression("name = #newName").getValue(context, person);
System.out.println(person.getName()); // "Mike Tesla"
}
/**
* Constructors
*/
@Test
public void testConstructors() {
// 通过构造器创建 Person 实例
Person einstein = parser.parseExpression("new study.spel.bean.Person('Albert Einstein', 20)").getValue(Person.class);
// 调用 company 的 personList 的 add 方法,并加入新建 person
parser.parseExpression("PersonList.add(new study.spel.bean.Person('Albert Einstein', 20))").getValue(company);
}
/**
* Types
*/
@Test
public void testTypes() {
Class dateClass = parser.parseExpression("T(java.util.Date)").getValue(Class.class); // class java.util.Date
Class stringClass = parser.parseExpression("T(String)").getValue(Class.class); // class java.lang.String
boolean trueValue = parser.parseExpression("T(java.math.RoundingMode).CEILING < T(java.math.RoundingMode).FLOOR").getValue(Boolean.class); // true
}
/**
* Operators - The Assignment Operator
*/
@Test
public void testOperatorsAssignment() {
context = SimpleEvaluationContext.forReadWriteDataBinding().build();
// 会设置 person 的 name 属性为 Aleksandar Seovic
// parser.parseExpression("name").setValue(context, person, "Aleksandar Seovic");
// 会设置 person 的 name 属性为 Aleksandar Seovic
String aleks = parser.parseExpression("name = 'Aleksandar Seovic'").getValue(context, person, String.class);
}
/**
* Operators - Mathematical Operators
*/
@Test
public void testMathematicalOperators() {
// 加法
int two = parser.parseExpression("1 + 1").getValue(Integer.class); // 2
// 字符串拼接
String testString = parser.parseExpression("'test' + ' ' + 'string'").getValue(String.class); // 'test string'
// 减法
int four = parser.parseExpression("1 - -3").getValue(Integer.class); // 4
double d = parser.parseExpression("1000.00 - 1e4").getValue(Double.class); // -9000
// 乘法
int six = parser.parseExpression("-2 * -3").getValue(Integer.class); // 6
double twentyFour = parser.parseExpression("2.0 * 3e0 * 4").getValue(Double.class); // 24.0
// 除法
int minusTwo = parser.parseExpression("6 / -3").getValue(Integer.class); // -2
double one = parser.parseExpression("8.0 / 4e0 / 2").getValue(Double.class); // 1.0
// 取模
int three = parser.parseExpression("7 % 4").getValue(Integer.class); // 3
int one1 = parser.parseExpression("8 / 5 % 2").getValue(Integer.class); // 1
// 运算符优先级
int minusTwentyOne = parser.parseExpression("1+2-3*8").getValue(Integer.class); // -21
}
/**
* Operators - Logical Operators
* <p>
* and (&&)
* or (||)
* not (!)
*/
@Test
public void testOperatorsLogicalOperators() {
// -- AND -- //
boolean falseValue = parser.parseExpression("true and false").getValue(Boolean.class);
String expression = "isMember('person0') and isMember('person1')";
boolean trueValue = parser.parseExpression(expression).getValue(company, Boolean.class);
// -- OR -- //
boolean trueValue2 = parser.parseExpression("true or false").getValue(Boolean.class);
expression = "isMember('person0') or isMember('person1')";
boolean trueValue3 = parser.parseExpression(expression).getValue(company, Boolean.class);
// -- NOT -- //
boolean falseValue2 = parser.parseExpression("!true").getValue(Boolean.class);
// -- AND and NOT -- //
expression = "isMember('Nikola Tesla') and !isMember('Mihajlo Pupin')";
boolean falseValue3 = parser.parseExpression(expression).getValue(company, Boolean.class);
}
/**
* Operators - Relational Operators
* <p>
* lt(<)
* gt(>)
* le(<=)
* ge(>=)
* eq(==)
* ne(!=)
* div(/)
* mod(%)
* not(!)
*/
@Test
public void testOperatorsRelationalOperators() {
boolean trueValue = parser.parseExpression("2 == 2").getValue(Boolean.class);
boolean trueValueEq = parser.parseExpression("2 eq 2").getValue(Boolean.class);
boolean falseValue = parser.parseExpression("2 < -5.0").getValue(Boolean.class);
boolean trueValue2 = parser.parseExpression("'black' < 'block'").getValue(Boolean.class);
// ----------------------------------------------------------------- //
boolean falseValue2 = parser.parseExpression("'xyz' instanceof T(Integer)").getValue(Boolean.class);
boolean trueValue3 = parser.parseExpression("'5.00' matches '^-?\\d+(\\.\\d{2})?$'").getValue(Boolean.class);
boolean falseValue3 = parser.parseExpression("'5.0067' matches '^-?\\d+(\\.\\d{2})?$'").getValue(Boolean.class);
}
/**
* Methods
*/
@Test
public void testMethods() {
String bc = parser.parseExpression("'abc'.substring(1, 3)").getValue(String.class); // bc
boolean hasBook = parser.parseExpression("hasBook('book0')").getValue(person, Boolean.class); // true
}
/**
* Array Construction
*/
@Test
public void testArrayConstruction() {
context = SimpleEvaluationContext.forReadOnlyDataBinding().build();
int[] numbers1 = (int[]) parser.parseExpression("new int[4]").getValue(context); // [0, 0, 0, 0]
// Array with initializer
int[] numbers2 = (int[]) parser.parseExpression("new int[]{1,2,3}").getValue(context); // [1, 2, 3]
// Multi dimensional array
int[][] numbers3 = (int[][]) parser.parseExpression("new int[4][5]").getValue(context); // [[0, 0, 0, 0, 0], [0, 0, 0, 0, 0], [0, 0, 0, 0, 0], [0, 0, 0, 0, 0]]
}
/**
* Inline Maps
*/
@Test
public void testInlineMaps() {
context = SimpleEvaluationContext.forReadOnlyDataBinding().build();
// 单层
Map inventorInfo = (Map) parser.parseExpression("{name:'Nikola',dob:'10-July-1856'}").getValue(context); // {name=Nikola, dob=10-July-1856}
// 多层嵌套
Map mapOfMaps = (Map) parser.parseExpression("{name:{first:'Nikola',last:'Tesla'},dob:{day:10,month:'July',year:1856}}").getValue(context); // {name={first=Nikola, last=Tesla}, dob={day=10, month=July, year=1856}}
}
/**
* Inline Lists
*/
@Test
public void testInlineLists() {
context = SimpleEvaluationContext.forReadOnlyDataBinding().build();
// evaluates to a Java list containing the four numbers
List numbers = (List) parser.parseExpression("{1,2,3,4}").getValue(context); // [1, 2, 3, 4]
List listOfLists = (List) parser.parseExpression("{{'a','b'},{'x','y'}}").getValue(context); // [[a, b], [x, y]]
}
@Test
public void testMap() {
Person dept0Leader = parser.parseExpression("deptCodeLeaderMap['dept0']").getValue(company, Person.class); // Person(name=person0 ...
String city = parser.parseExpression("deptCodeLeaderMap['dept0'].birthPlace.city").getValue(company, String.class); // city0
// 设置值
parser.parseExpression("deptCodeLeaderMap['dept1'].birthPlace.country").setValue(company, "country0xx");
String dept1Country = parser.parseExpression("deptCodeLeaderMap['dept1'].birthPlace.country").getValue(company, String.class); // country0xx
}
@Test
public void testArrayList() {
context = SimpleEvaluationContext.forReadOnlyDataBinding().build();
String book2 = parser.parseExpression("books[2]").getValue(context, person, String.class); // book2
String person0Name = parser.parseExpression("personList[0].name").getValue(context, company, String.class); // person0
String person0Book2 = parser.parseExpression("personList[0].books[1]").getValue(context, company, String.class); // book1
// parser.parseExpression("deptCodeLeaderMap['dept1'].birthPlace.country").setValue(context, company, "country0xx"); // org.springframework.expression.spel.SpelEvaluationException: EL1010E: Property or field 'country' cannot be set on object of type 'study.spel.bean.BirthPlace' - maybe not public or not writable?
}
/**
* Properties, Arrays, Lists, Maps, and Indexers
*/
@Test
public void testProperties() {
int year = (Integer) parser.parseExpression("birthday.year + 1900").getValue(person); // 2012
String city = (String) parser.parseExpression("birthPlace.city").getValue(person); // city0
}
/**
* 字面值
*/
@Test
public void testLiteralExpressions() {
// 字符串
String helloWorld = (String) parser.parseExpression("'Hello World'").getValue(); // Hello World
// double
double d = (double) parser.parseExpression("1.234").getValue(); // 1.234
// double,科学计数法
double avogadrosNumber = (Double) parser.parseExpression("6.0221415E+23").getValue(); // 6.0221415E23
// 16 进制
int maxValue = (Integer) parser.parseExpression("0x7FFFFFFF").getValue(); // 2147483647
// 布尔值
boolean trueValue = (Boolean) parser.parseExpression("true").getValue(); // true
// NULL
Object nullValue = parser.parseExpression("null").getValue(); // null
}
}