一、SnEL 是什么?
Solon Expression Language(简称SnEL)是 Solon 生态体系中的轻量级表达式引擎,专为Java开发者设计。它采用独特的"求值表达式"模型,通过简洁的语法实现复杂逻辑处理,同时保持极高的执行效率和安全性。
项目地址:
二、核心特性解析
1. 安全可靠的表达式引擎
- 无副作用设计:禁止
new实例化、控制语句等危险操作 - 上下文隔离:通过
StandardContext严格管控变量访问范围
2. 丰富的表达式能力
// 复杂逻辑表达式示例 String expr = """ ((age > 18 AND salary < 5000) OR NOT isMarried) AND tags IN ['vip','premium'] OR level == 'gold'""";
支持功能主要包括:
- 基础运算:算术、比较、逻辑运算
- 集合操作:IN/NOT IN集合判断
- 嵌套访问:多级对象属性/方法调用
- 静态方法:直接调用类静态方法
- 三元运算:条件表达式支持
更多参考官网:《SnEL 求值表达式语法和能力说明》
3. 独创的模板引擎
双模式模板处理:
// 求值表达式模板 SnEL.evalTmpl("订单总额:#{order.amount * 0.95}"); // 属性表达式模板(带默认值) SnEL.evalTmpl("配置参数:${server.timeout:3000}");
三、企业级功能深度解析
1. 上下文增强方案
// 标准Map上下文 Map<String,Object> ctx = new HashMap<>(); ctx.put("user", userService.getCurrent()); // 增强型Bean上下文 StandardContext context = new StandardContext(userEntity); context.properties(configProps); // 绑定配置属性 // 虚拟root访问 SnEL.eval("root.id > 1000", context);
2. 多场景表达式转换
基于AST的通用转换接口:
Expression expr = SnEL.parse("age > 18 AND status=='active'"); // 转换为Redis查询语法 String redisFilter = RedisFilterTransformer.getInstance().transform(expr); // 转换为Elasticsearch DSL Map<String,Object> esQuery = ElasticsearchFilterTransformer.getInstance().transform(expr); // 输出语法树结构 PrintUtil.printTree(expr);
| 转换器类型 | 输出示例 | 应用场景 |
|---|---|---|
| Redis | (@age:[18 +inf] @status:{active}) |
缓存查询 |
| Milvus | ((metadata["age"] > 18) and (metadata["status"] == "active")) |
向量数据库 |
| Elasticsearch | {bool={must=[{range={age={gt=18}}}, {term={status={value=active}}}]}} |
全文检索 |
| SQL | WHERE age > 18 AND status='active' |
数据库查询 |
四、典型应用场景
- 动态规则引擎:金融风控规则配置
- 智能路由:微服务调用条件路由
- 低代码平台:表单校验逻辑动态配置
- 数据分析:实时数据过滤与计算
五、快速入门
1. 添加依赖
<dependency> <groupId>org.noear</groupId> <artifactId>solon-expression</artifactId> <version>最新版本</version> </dependency>
2. 基础用法示例
public class Demo { public static void main(String[] args) { Map<String,Object> context = new HashMap<>(); context.put("price", 99.5); context.put("discount", 0.8); Object result = SnEL.eval("price * discount > 50", context); System.out.println("是否符合条件:" + result); } }
3. 性能优化建议
- 复用解析结果:对固定表达式使用 SnEL.parse() 缓存 AST
- 上下文优化:复杂对象优先使用 StandardContext
- 避免频繁解析:高并发场景预编译表达式
六、企业实践案例
案例1:电商促销系统
// 动态计算促销条件 String rule = """ (user.level IN ['VIP','SVIP'] OR order.amount > 1000) AND inventory.stock > 0 AND NOT blacklist.contains(user.id)"""; Boolean rst = SnEL.eval(rule, context);
案例2:物联网数据处理
// 设备数据过滤规则 String filter = """ (data.temperature > 38.5 OR data.humidity < 20) AND meta.deviceType == 'medical'"""; // 转换为MQTT Topic过滤语法(需要自已定制 IotTransformer) String mqttFilter = IotTransformer.transform(SnEL.parse(filter));