一、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));

Solon Expression Language (SnEL):轻量高效的Java表达式引擎的更多相关文章

  1. Vue.js:轻量高效的前端组件化方案

    转发一篇尤老师对vue.js的介绍,了解vue.js的来龙去脉.不过现在已经是2.0了,也有添加一些新的东西,当然有些东西也改了. Vue.js:轻量高效的前端组件化方案 Vue.js 是我在2014 ...

  2. Vue.js:轻量高效的前端组件化方案(转载)

    摘要:Vue.js通过简洁的API提供高效的数据绑定和灵活的组件系统.在前端纷繁复杂的生态中,Vue.js有幸受到一定程度的关注,目前在GitHub上已经有5000+的star.本文将从各方面对Vue ...

  3. 【转】Vue.js:轻量高效的前端组件化方案

    摘要:Vue.js通过简洁的API提供高效的数据绑定和灵活的组件系统.在前端纷繁复杂的生态中,Vue.js有幸受到一定程度的关注,目前在GitHub上已经有5000+的star.本文将从各方面对Vue ...

  4. 轻量高效的开源JavaScript插件和库 【转】

    图片 布局 轮播图 弹出层 音频视频 编辑器 字符串 表单 存储 动画 时间 其它 加载器 构建工具 测试 包管理器 CDN 图片 baguetteBox.js - 是一个简单易用的响应式图像灯箱效果 ...

  5. 2016年31款轻量高效的开源JavaScript插件和库

    目前有很多网站设计师和开发者喜欢使用由JavaScript开发的插件和库,但同时面临一个苦恼的问题:它们中的大多数实在是太累赘而且常常降低网站的性能.其实,其中也有不少轻量级的插件和库,它们不仅轻巧有 ...

  6. 2016年31款轻量高效的开源 JavaScript 插件和库

    目前有很多网站设计师和开发者喜欢使用由JavaScript开发的插件和库,但同时面临一个苦恼的问题:它们中的大多数实在是太累赘而且常常降低网站的性能.其实,其中也有不少轻量级的插件和库,它们不仅轻巧有 ...

  7. 2016 年 31 款轻量高效的开源 JavaScript 插件和库

    目前有很多网站设计师和开发者喜欢使用由JavaScript开发的插件和库,但同时面临一个苦恼的问题:它们中的大多数实在是太累赘而且常常降低网站的性能.其实,其中也有不少轻量级的插件和库,它们不仅轻巧有 ...

  8. 【Juicer】 一个高效、轻量的前端 (Javascript) 模板引擎

    引用地址:http://juicer.name/docs/docs_zh_cn.html * 一个完整的例子 HTML 代码: <script id="tpl" type=& ...

  9. 推荐轻量高效无依赖的开源JS插件和库

    目录 图片 布局 音频视频 编辑器 轮播图 弹出层 表单 存储 动画 时间 其它 CDN 图片 baguetteBox.js - 是一个简单易用的响应式图像灯箱效果脚本.demo Lightgalle ...

  10. 39行代码实现JS HTML模板(轻量+高效+易用)

    otmpl 是一个轻量级前端模版(仅有39行无压缩代码,支持缓存),所用指令仅需[#...#]和{#...#},前者包含需要输出html语句,后者包含js变量. 支持javascript完整语法,你可 ...

随机推荐

  1. MySQL函数-根据子节点查询所有父节点名称

    背景 公司的一个业务系统中有区域表,整个区域是一个树结构,为了方便根据某一父节点查询所有叶子节点,提供了一个额外的字段path,按照分隔符存储了从根节点到当前节点的总路径. 表结构如下: create ...

  2. 【SpringCloud】OpenFeign服务接口调用

    OpenFeign服务接口调用 概述 我的理解: feign 为什么叫伪装? Feign可以把Rest的请求进行隐藏,伪装成类似SpringMVC的Controller一样.你不用再自己拼接url,拼 ...

  3. android点滴-1

    一.关于TSpeedButtons 1.对于TspeedButtons,需要选择适当的StyleLookUp值后,才能在ObjectInspector中出现TintColor属性,根据自己需要进行修改 ...

  4. Nginx+Windows搭建域名访问环境, 由nginx --> 网关 ---> 服务

    1).修改windows hosts文件改变本地域名映射,将gulimall.com映射到虚拟机ip 2).修改nginx的根配置文件nginx.conf,将upstream映射到我们的网关服务 up ...

  5. mysql分区自动维护(SpringBoot+MybatisPlus)

    1.环境 SpringBoot + MybatisPlus + MySQL 2.简介 通过定时器@Scheduled每日触发,查询当前库中所有分区表(这里以时间段进行分区) 判断剩余分区是否小于自定义 ...

  6. DPDI(Dispatch PDI)kettle调度管理平台介绍

    DPDI online产品简介 DPDI Online 是一款基于Kettle的强大在线任务调度平台,凭借其高效与灵活性,专为调度和监控Kettle客户端生成的ETL任务而设计 DPDI Online ...

  7. K8s容器运行时,移除Dockershim后存在哪些疑惑?

    K8s容器运行时,移除Dockershim后存在哪些疑惑? 大家好,我是秋意零. K8s版本截止目前(24/09)已经发布到了1.31.x版本.早在K8s版本从1.24.x起(22/05),默认的容器 ...

  8. SpringBoot项目创建的三种方式

    目录 1 通过官网创建 2 通过IDEA脚手架创建 2.1 IDEA新建项目 2.2 起Group名字,选择Java版本,点击Next 2.3 选择Web依赖,选择Spring Web,确认Sprin ...

  9. 【从0到1800 Star】90天,我用0预算推广了一个C语言项目

    亲爱的朋友们,我想和你们分享一下这90多天的开发旅程,虽然不涉及具体的技术部分,但我相信这些经验对你的项目会有所帮助哦 Catime是如何在大约90天内从0做到1800+ star的呢?其中最主要的原 ...

  10. MarchingCube算法之C#实现三维❤

    首先致谢该博文,讲解的非常详细:https://blog.csdn.net/u013339596/article/details/19167907?spm=1001.2101.3001.6650.7& ...