Spring Expression Language(SpEL) 是一个表达式语言,可以用来在运行时查询和操作对象图,比较类似于EL表达式,相比其他的表达式语言,可以更好的与Spring集成,如果使用Spring的话,也可以不用再引入额外的依赖
同时它也是可以单独引入并且使用的,这里我们主要就是看一下单独使用的情况下它能做什么以及如何使用
首先需要引入依赖包
1 2 3 4 5
| <dependency> <groupId>org.springframework</groupId> <artifactId>spring-expression</artifactId> <version>5.3.12</version> </dependency>
|
普通表达式求值
1 2 3 4 5 6 7 8 9 10 11 12
| ExpressionParser parser = new SpelExpressionParser();
String helloWorld = parser.parseExpression("'Hello World'").getValue(String.class);
Expression expression = parser.parseExpression("'hello' + ' world'"); String value = expression.getValue(String.class);
Expression expression1 = parser.parseExpression("5 + 8"); Integer v1 = expression1.getValue(Integer.class);
|
在表达式中,支持各种关系、算数、逻辑表达式,同时还可以调用相关的类或者方法
1 2 3 4 5 6 7
| Expression expression = parser.parseExpression("('hello' + ' world').toUpperCase()"); String value = expression.getValue(String.class);
Boolean value1 = parser.parseExpression("T(org.apache.commons.lang3.StringUtils).isNoneBlank('aa')").getValue(Boolean.class);
|
操作对象
当需要使用表达式解析属性、方法等时,都需要用到EvaluationContext
这个接口,只不过当我们没有显示提供的时候,SpEL会自动创建一个实现StandardEvaluationContext
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| User user = new User(); user.setUserName("zhangsan"); user.setAge(18); EvaluationContext context = new StandardEvaluationContext(user);
ExpressionParser parser = new SpelExpressionParser(); Expression expression = parser.parseExpression("#root.userName"); String value = expression.getValue(context, String.class);
public class User { private String userName; private Integer credits; }
|
对于只有一个rootObject的情况,可以不显示指定EvaluationContext,即上述写法可以简化为
1 2 3 4 5 6
| User user = new User(); user.setUserName("zhangsan"); user.setAge(18);
String userName = parser.parseExpression("userName").getValue(user, String.class);
|
但是如果除了rootObject外还需要设置其他属性的话,那么EvaluationContext就不能省略了
1 2 3 4 5 6 7 8 9 10 11 12 13
| User user = new User(); user.setUserName("zheng"); user.setAge(18); EvaluationContext context = new StandardEvaluationContext(user);
context.setVariable("addAge", 10);
ExpressionParser parser = new SpelExpressionParser(); Expression expression = parser.parseExpression("age + #addAge"); Integer value = expression.getValue(context, Integer.class);
|
同时使用SpEL不仅可以用来读取对象,还可以用来修改对象的值
1 2 3 4 5 6 7 8 9 10 11
| User user = new User(); user.setUserName("zhangsan"); user.setAge(18);
ExpressionParser parser = new SpelExpressionParser(); Expression expression = parser.parseExpression("userName");
expression.setValue(user, "lisi");
String res = user.getUserName();
|
集合操作
可以用过SpEL表达式实现集合过滤和数据转换操作
过滤
通过.?[selectionExpression]
可以对集合中的元素进行筛选过滤
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| List<User> userList = new ArrayList<>(); { User user = new User(); user.setUserName("zhangsan"); user.setAge(18); userList.add(user); } { User user = new User(); user.setUserName("lisi"); user.setAge(10); userList.add(user); } { User user = new User(); user.setUserName("wangwu"); user.setAge(20); userList.add(user); } ExpressionParser parser = new SpelExpressionParser(); final Expression expression = parser.parseExpression("#this.?[age > 10]"); final List<User> value = expression.getValue(userList, List.class);
|
过滤操作还可以用于map类型的数据
1 2 3 4 5 6 7 8
| Map<String, Integer> map = new HashMap<>(); map.put("key1", 10); map.put("key2", 20); map.put("key3", 30); ExpressionParser parser = new SpelExpressionParser(); final Expression expression = parser.parseExpression("#root.?[value>10]"); final Map value = expression.getValue(map, Map.class);
|
如果过滤的时候只想取满足条件的第一个值或者最后一个值,可以使用.^[selectionExpression]
或者.$[selectionExpression]
来分别获取
1 2 3 4 5 6 7
| Expression expression1 = parser.parseExpression("#this.^[age>10]"); Object value1 = expression1.getValue(userList);
Expression expression2 = parser.parseExpression("#this.$[age>10]"); Object value2 = expression2.getValue(userList);
|
数据映射转换
通过.![projectionExpression]
可以对数据进行转换
1 2 3 4 5 6 7 8
| List<User> userList = new ArrayList<>();
ExpressionParser parser = new SpelExpressionParser();
Expression expression = parser.parseExpression("#this.![age]"); List<?> value = expression.getValue(userList, List.class);
|
其他
Elvis操作符
这个操作符相当于对?:
这个三元操作符的简化,比如当左侧表达式不为null时返回值本身,否则返回一个固定值
1 2 3 4 5
| String realName = name != null ? name : 'Guest';
String realName = name ?: 'Guest';
|
使用示例
1 2 3 4 5 6 7 8 9 10
| User user = new User();
ExpressionParser parser = new SpelExpressionParser(); Expression expression = parser.parseExpression("userName ?: 'Guest'"); String value = expression.getValue(user, String.class);
user.setUserName("zhangsan"); value = expression.getValue(user, String.class);
|
安全导航操作符
对于在取属性时可能遇到的空指针问题,如获取user的姓名时,我们通常需要判断user是否为null,这种代码比较啰嗦,取值时可以使用?.
方式进行简化
1 2 3 4 5 6 7
| User user = null;
ExpressionParser parser = new SpelExpressionParser();
Expression expression = parser.parseExpression("#root?.userName"); String value = expression.getValue(user, String.class);
|
Elvis操作符和安全导航操作符在Groovy中也有同样的功能
参考资料:https://docs.spring.io/spring-framework/docs/current/reference/html/core.html#expressions