SnEL 求值表达式语法和能力说明
1、SnEL 求值接口说明
接口 | 描述 |
---|---|
SnEL.parse(...) | 解析求值表达式 |
SnEL.eval(...) | 执行求值表达式 |
2、语法与能力说明
能力 | 示例 | 备注 |
---|---|---|
支持常量获取 | 1 , 'name' , true , [1,2,3] | 数字、字符串、布尔、数组 |
支持变量获取 | name | |
支持字典获取 | map['name'] | |
支持集合获取 | list[0] | |
支持对象属性或字段获取 | user.name , user['name'] | 支持. 或 [] |
支持对象方法获取 | order.getUser() , list[0].getUser() | 支持多级嵌套 |
支持对象静态方法获取 | Math.add(1, 2) , Math.add(a, b) | 支持多级嵌套 |
支持优先级小括号 | ( , ) | |
支持算数操作符 | + , - , * , / , % | 加,减,乘,除,模 |
支持比较操作符 | < , <= , > , >= , == , != | 结果为布尔 |
支持like操作符 | LIKE , NOT LIKE (在相当于包含) | 结果为布尔 |
支持in操作符 | IN , NOT IN | 结果为布尔 |
支持三元逻辑操作符 | conditionExpr ? trueExpr: falseExpr | |
支持二元逻辑操作符 | AND , OR | 与,或(兼容 && 、|| ) |
支持一元逻辑操作符 | NOT | 非(兼容 ! ) |
支持安全导航表达式 (Elvis操作符) | user?.name (不加? 效果相同) | 如果不为 null 则导航。v2.5.2 后支持 |
支持默认值表达式 (Elvis操作符) | user.name ?: 'noear' | 如果为 null 则用默认值。v3.5.2 后支持 |
支持属性表达式 | ${user.name} , ${user.name:noear} | 以 key 的方式取值。v3.5.2 后支持 |
支持类型表达式 | T(java.lang.Integer).valueOf(45) | 使用一个类型的静态方法。v3.6.0 后支持 |
虚拟变量(root)说明:
当使用 EnhanceContext 上下文时,支持 root
虚拟变量(SnEL.eval("root == true", new EnhanceContext(true))
)
关键字须使用全大写(未来还可能会增多):
LIKE
, NOT LIKE
, IN
, NOT IN
,AND
, OR
,NOT
数据类型与符号说明:
1.1F
(单精度)、1.1D
(双精度)、1L
(长整型)。1.1
(双精度)、1
(整型)
Elvis 操作符号:
?.
(安全导航表达式), ?:
(默认值表达式)
属性表达式操作符号:
${ }
(属性表达式会从 PropertiesGuidance
接口优先获取。如果没有?再以 key
方式从 context
获取)
预留特殊符号:
#{ }
, 用于模板表达式
3、表达式示例
- 常量与算数表达式
System.out.println(SnEL.eval("1"));
System.out.println(SnEL.eval("-1"));
System.out.println(SnEL.eval("1 + 1"));
System.out.println(SnEL.eval("1 * (1 + 2)"));
System.out.println(SnEL.eval("'solon'"));
System.out.println(SnEL.eval("true"));
System.out.println(SnEL.eval("[1,2,3,-4]"));
- 变量,字典,集合获取
Map<String, String> map = new HashMap<>();
map.put("code", "world");
List<Integer> list = new ArrayList<>();
list.add(1);
Map<String, Object> context = new HashMap<>();
context.put("name", "solon");
context.put("list", list);
context.put("map", map);
System.out.println(SnEL.eval("name.length()", context)); //顺便调用个函数
System.out.println(SnEL.eval("name.length() > 2 OR true", context));
System.out.println(SnEL.eval("name.length() > 2 ? 'A' : 'B'", context));
System.out.println(SnEL.eval("map['code']", context));
System.out.println(SnEL.eval("list[0]", context));
System.out.println(SnEL.eval("list[0] == 1", context));
- 带优先级的复杂逻辑表达式
Map<String, Object> context = new HashMap<>();
context.put("age", 25);
context.put("salary", 4000);
context.put("isMarried", false);
context.put("label", "aa");
context.put("title", "ee");
context.put("vip", "l3");
String expression = "(((age > 18 AND salary < 5000) OR (NOT isMarried)) AND label IN ['aa','bb'] AND title NOT IN ['cc','dd']) OR vip=='l3'";
System.out.println(SnEL.eval(expression, context));
- 静态函数调用表达式
Map<String, Object> context = new HashMap<>();
context.put("Math", Math.class);
System.out.println(SnEL.eval("Math.abs(-5) > 4 ? 'A' : 'B'", context));
- Elvis 操作符表达式(v3.5.2 后支持)
//安全导航 和 默认值
System.out.println(SnEL.eval("user?.name ?: 'solon'"));
System.out.println(SnEL.eval("user.name ?: 'solon'")); //两都效果相同
T(className)
类型操作符表达式(v3.6.0 后支持)
System.out.println(SnEL.eval("T(java.lang.Integer).parseInt(${user.age:12}) + 13")); //=>25
4、属性表达式的增强效应
属性表达式参与逻辑运算和比较运算时,可自动转换类型。
- 参与逻辑运算
参与逻辑运行时,会自动转为 bool 型。当非空时为 true, 否则为 false
SnEL.eval("${demo.aaa} && bbb > 2");
- 参与比较运算
参与比较运算时,会自动转为比较目标的类型,再进行比较。
SnEL.eval("${demo.aaa:true} == 'true'"); //原始态
SnEL.eval("${demo.aaa:true} == true"); //转为 bool
SnEL.eval("${demo.aaa:12} > 20"); //转为 number
5、嵌入对象(仅为示例)
Map<String, Object> context = new HashMap<>();
context.put("Solon", Solon.class);
context.put("_sysProps", Solon.cfg()); //顺便别的对象(供参考)
context.put("_sysEnv", System.getenv());
//顺便用三元表达式,模拟下 if 语法
String expr = "Solon.cfg().getInt('demo.type', 0) > _sysProps.getInt('') ? Solon.context().getBean('logService').log(1) : 0";
System.out.println(SnEL.eval(expr, context));
属性表达式
//求值
System.out.println(SnEL.eval("${user.name:solon}", Solon.cfg()));
System.out.println(SnEL.eval("'Hello ' + ${user.name:solon}", Solon.cfg()));
//模板
System.out.println(SnEL.evalTmpl("Hello ${user.name:solon}", Solon.cfg()));