# Simply Expression Language
**Repository Path**: fanjr/simplify-el
## Basic Information
- **Project Name**: Simply Expression Language
- **Description**: 简易表达式(simply-el),旨在解决判断、计算、取值、结构转换这些逻辑简单但编码繁复的工作
- **Primary Language**: Java
- **License**: Apache-2.0
- **Default Branch**: master
- **Homepage**: None
- **GVP Project**: No
## Statistics
- **Stars**: 4
- **Forks**: 1
- **Created**: 2023-02-02
- **Last Updated**: 2026-03-23
## Categories & Tags
**Categories**: Uncategorized
**Tags**: 表达式, el, expression-language
## README
# Simply Expression Language
##### [📖 English Documentation](README_en.md) | 📖 中文文档
[](https://openjdk.java.net/)
[](https://github.com/FanJiaRui/Simply-Expression-Language/releases)
[](https://search.maven.org/artifact/net.fanjr.simplify/simplify-el)
[](https://www.apache.org/licenses/LICENSE-2.0.html)
## 介绍
简易表达式语言,旨在解决判断、计算、取值、结构转换这些逻辑简单但编码繁复的工作。
**主要应用场景**:动态规则计算、类型适配(报文转换),可配合调度类、流程类引擎的动态计算。
## 特性
- **安全取值**:告别频繁繁琐的空判断,链式取值自动处理 null
- **层级结构**:快速操作、转换 JSON 或各类 POJO
- **分支逻辑**:支持 if-else / for 循环 / 三元表达式
- **方法调用**:直接调用 Java 对象方法,支持自定义工具方法
- **内置函数**:38 个内置函数覆盖字符串、集合、类型、数学、日期
- **使用便捷**:无需额外构建上下文对象,直接计算原生对象
## 环境要求
| 依赖 | 版本 |
|------|------|
| JDK | 1.8+ |
| fastjson2 | 2.0.56 |
| slf4j | 1.7.30 |
## 引入配置
```xml
net.fanjr.simplify
simplify-el
2.0.0
```
> 1.1.0 及更早版本使用 `org.fanjr.simplify` 的 groupId
## 快速开始
### 基本求值
```java
// 条件判断
boolean result = ELExecutor.eval("a==100", "{\'a\':100}", boolean.class);
// true
// 四则运算
int result = ELExecutor.eval("2 * a - (b + c) * d",
"{\'a\':1,\'b\':2,\'c\':3,\'d\':4}", int.class);
// 2*1-(2+3)*4 = -18
// 正则匹配
boolean match = ELExecutor.eval("phone ~= \'^[0-9]{11}$\'",
JSONObject.of("phone","18888888888"), boolean.class);
// true
```
### 赋值与计算
```java
Map ctx = new HashMap<>();
ctx.put("val", 10);
ELExecutor.eval("a=10; val=val+1; val++; result=a+val;", ctx);
// a=10, val=12, result=22
```
### 安全取值(POJO/JSON)
```java
// 自动处理 null,无需逐层判断
TestReq req = new TestReq();
ELExecutor.eval("head.serialId=\'123456\'", req);
// req.getHead().getSerialId() == "123456"
```
### 方法调用
```java
Map ctx = new HashMap<>();
ctx.put("val", "010");
int len = ELExecutor.eval("((int)val).toString().length()", ctx, int.class);
// "010" → 10 → "10" → length() = 2
```
### 三元表达式
```java
Map ctx = new HashMap<>();
ctx.put("flag", 100);
ctx.put("val", 10);
int result = ELExecutor.eval("flag>=100 ? val*10 : val/10", ctx, int.class);
// 100
```
### 分支语句
```java
Map ctx = new HashMap<>();
ctx.put("flag", 2);
ELExecutor.eval("if(flag==1){ a=1; } else if(flag==2){ a=2; a++; } else { a=0; }", ctx);
// a = 3
```
### 循环语句
```java
Map ctx = new HashMap<>();
// 类 C 模式
ELExecutor.eval("for(i=0; i<10; i++){ arr[i] = i*3 }", ctx);
// 迭代器模式
ctx.put("nums", new int[]{1,2,3});
ELExecutor.eval("for(n : nums){ sum += n }", ctx);
// 数字模式(等价于 i=0; i<10; i++)
ELExecutor.eval("for(i : 10){ arr[i] = i }", ctx);
```
## 内置函数
通过 `$.函数名()` 调用,共 38 个内置函数:
### 字符串操作
| 函数 | 说明 | 示例 |
|------|------|------|
| `$.trim(s)` | 去首尾空格 | `$.trim(\' hi \')` → `\'hi\'` |
| `$.upper(s)` | 转大写 | `$.upper(\'hello\')` → `\'HELLO\'` |
| `$.lower(s)` | 转小写 | `$.lower(\'HELLO\')` → `\'hello\'` |
| `$.split(s, sep)` | 分割 | `$.split(\'a,b\', \',\')` → `[\'a\',\'b\']` |
| `$.replace(s, old, new)` | 替换 | `$.replace(\'hello\', \'l\', \'r\')` → `\'herro\'` |
| `$.contains(s, sub)` | 包含判断 | `$.contains(\'hello\', \'ell\')` → `true` |
| `$.startsWith(s, prefix)` | 前缀判断 | `$.startsWith(\'hello\', \'he\')` → `true` |
| `$.endsWith(s, suffix)` | 后缀判断 | `$.endsWith(\'hello\', \'lo\')` → `true` |
| `$.substring(s, start, end)` | 截取 | `$.substring(\'hello\', 1, 3)` → `\'el\'` |
| `$.len(s)` | 长度(字符串/集合/数组) | `$.len(\'hello\')` → `5` |
### 集合操作
| 函数 | 说明 | 示例 |
|------|------|------|
| `$.size(col)` | 集合/Map/数组大小 | `$.size([1,2,3])` → `3` |
| `$.isEmpty(obj)` | 空判断(null/空串/空集合) | `$.isEmpty(null)` → `true` |
| `$.isNotEmpty(obj)` | 非空判断 | `$.isNotEmpty(\'a\')` → `true` |
| `$.toList(arr)` | 转为 List | `$.toList(arr)` → `List` |
### 类型转换
| 函数 | 说明 | 示例 |
|------|------|------|
| `$.isNull(obj)` | null 判断 | `$.isNull(null)` → `true` |
| `$.isNotNull(obj)` | 非 null 判断 | `$.isNotNull(\'a\')` → `true` |
| `$.str(obj)` | 转字符串 | `$.str(123)` → `\'123\'` |
| `$.toInt(obj)` | 转整数 | `$.toInt(\'123\')` → `123` |
| `$.toLong(obj)` | 转长整数 | `$.toLong(\'123\')` → `123L` |
| `$.toDouble(obj)` | 转浮点数 | `$.toDouble(\'1.5\')` → `1.5` |
| `$.toBool(obj)` | 转布尔 | `$.toBool(1)` → `true` |
### 数学运算
| 函数 | 说明 | 示例 |
|------|------|------|
| `$.max(a, b)` | 取大值 | `$.max(3, 5)` → `5` |
| `$.min(a, b)` | 取小值 | `$.min(3, 5)` → `3` |
| `$.abs(n)` | 绝对值 | `$.abs(-5)` → `5` |
| `$.round(n, scale)` | 四舍五入 | `$.round(3.1415, 2)` → `3.14` |
| `$.ceil(n)` | 向上取整 | `$.ceil(3.1)` → `4` |
| `$.floor(n)` | 向下取整 | `$.floor(3.9)` → `3` |
### 日期操作
| 函数 | 说明 | 示例 |
|------|------|------|
| `$.now()` | 当前时间戳(毫秒) | `$.now()` → `1711123200000` |
| `$.formatDate(ts, fmt)` | 格式化日期 | `$.formatDate($.now(), \'yyyy-MM-dd\')` |
### 工具方法
| 函数 | 说明 | 示例 |
|------|------|------|
| `$.println(obj)` | 控制台输出(换行) | `$.println(\'hello\')` |
| `$.printf(str)` | 控制台输出(不换行) | `$.printf(\'hello\')` |
| `$.debug/info/warn/error(obj)` | 日志输出 | `$.info(\'msg\')` |
| `$.close(obj)` | 关闭资源 | `$.close(stream)` |
| `$.merge([m1,m2,...])` | 深度合并多个 Map | `$.merge([map1, map2])` |
| `$.getEnumMap(cls)` | 获取枚举映射 | `$.getEnumMap(\'com.xxx.Status\')` |
| `$.new(cls)` | 实例化对象 | `$.new(\'com.xxx.User\')` |
## 自定义函数扩展
在 `META-INF/simplify-el.functions` 中配置:
```properties
# 工具名=类全限定名(多个用逗号隔开)
$=net.fanjr.simplify.el.InnerFunctions
myTool=com.example.MyFunctions
```
用 `@ELMethod` 注解标记方法:
```java
public class MyFunctions {
@ELMethod
public static String hello(String name) {
return "Hello, " + name + "!";
}
}
```
调用:`myTool.hello(\'world\')` → `\'Hello, world!\'`
## 详细文档
[**📖 查看完整文档**](docs/document.md)
## 版本历史
| 版本 | 说明 |
|------|------|
| **2.0.0** | 架构升级,新增 26 个内置函数,错误信息增强 |
| **1.3.1** | 稳定版,修复已知问题 |
| **1.1.1** | GroupId 更换为 net.fanjr.simplify |
| **1.1.0** | 首个稳定版 |
## 许可证
[Apache License 2.0](https://www.apache.org/licenses/LICENSE-2.0.html)