一个 GitHub + Gitee 8k Star 的国产开源框架的反向押注:
注解就是配置,扩展点是 Spring Bean,AI 是默认依赖——没有"生成"这个动词。
一、先问个扎心的问题
随便找一个写了 5 年 Spring Boot 的后端,问他怎么看"低代码"——
我打赌你能在 30 秒内听到这三句话:
"我才不用,画布生成的那一坨代码我都不敢改。"
"调试就是看后台日志,没法 breakpoint。"
"业务一复杂就装不下,最后还是要拉一份 Git 仓库写代码。"
你看,开发者抵触低代码,理由从来不是"代码少了",是代码不在他熟悉的地方——
不在 IDE,不在 Git,不在 breakpoint 上。
国内现在主流的低代码产品有两条路,都没把控制权留给开发者:
📦 拖拽画布派——钉钉宜搭、腾讯微搭、简道云、明道云。配置在 SaaS 后台。
📝 拖拽 + 在线脚本派——JeecgBoot 在线表单 + Online Code、宜搭/微搭的 JS 编辑器、简道云智能助手、若依代码生成器。控制权一半在 IDE,一半在画布——而它俩之间永远在漂移,你回 IDE 改一行,下次想用画布加字段就要承担同步成本。
今天讲第三条路。
它的名字叫 Erupt,一个 GitHub 上 6.2k Star 的开源 Java 后台框架。
它押的不是"少写代码"——是把每一行控制权完整地留在 IDE 里,外加一份装好就能用的 AI Harness。
二、开发者讨厌低代码的三件事,逐条拆给你看
我把后端工程师抵触低代码的 7 件事摆成一张表,看完你就明白 Erupt 到底在做什么:
| 抵触点 | 拖拽派 (宜搭/简道云) | 拖拽+脚本派 (JeecgBoot/微搭) | Erupt |
|---|---|---|---|
| 控制权在哪 | SaaS 内部 DB | 一半生成代码,一半画布 | Git 里的 .java 源文件 |
| 怎么调试 | 看后台日志 | console.log + 平台日志 | IDE breakpoint |
| 怎么 diff | 截图对比 | git diff 自动生成代码(噪音大) | git diff 注解 |
| 复杂逻辑上限 | 表单事件 + JS | 在线 IDE,文件不在本机 | 任意 Spring Bean |
| CI/CD | 应用包导入导出 | jar + SQL 同步 | mvn package → jar |
| 单元测试 | 几乎不可能 | 下载到本机才能跑 | JUnit + H2 内存库 |
| AI 能力 | 需买"AI 加件" | 需外接 LangChain / Coze | erupt-ai 是默认依赖 |
最后一行是这篇文章的第二个核心。
当国内所有低代码厂商都在卷"低代码 + AI 加件"的时候,Erupt 把 AI Harness 做成了默认依赖——你引完 starter,17 个 LLM provider 已经在那里,扩展点也已经在那里,只差你把 API key 填进去。
三、"可控"在工程语境里到底是什么意思
听到"可控"两个字,国内厂商最常翻译成"可视化配置项更多"——能拖的字段更多、能配的规则更多。
这跟工程师想要的"可控"是两个东西。
工程师视角的"可控"非常具体:
✅ 每一行代码都在我 IDE 里——按 ⌘+B 能跳到定义
✅ 每一个状态都在 Git 里——git log 能看到谁在哪天改了哪个字段
✅ 每一个分支都可 review——git diff 是给人看的,不是机器生成的 1200 行 Vue
✅ 每一个错误都可 breakpoint——断点 + step over,而不是去翻不在本机的运行时日志
✅ 每一个扩展点都是 Spring Bean——熟悉的 @Service、@Autowired、@Transactional
Erupt 给的就是这五条。
来看一个最小例子,一个客户管理后台:
@Erupt(
name = "客户",
dataProxy = CustomerDataProxy.class,
power = @Power(importable = true, export = true)
)
@Table(name = "t_customer")
@Entity
public class Customer extends BaseModel {
@EruptField(
views = @View(title = "客户名"),
edit = @Edit(title = "客户名", notNull = true,
search = @Search(vague = true))
)
private String name;
@EruptField(
views = @View(title = "等级"),
edit = @Edit(title = "等级", type = EditType.CHOICE,
choiceType = @ChoiceType(vl = {
@VL(value = "A", label = "A 类"),
@VL(value = "B", label = "B 类")
}))
)
private String level;
}
两个字段、几行注解,Erupt 直接给你生成:
- 列表页(含搜索框、Excel 导入导出按钮)
- 新建 / 编辑表单
- 详情页
- 字段校验
- 权限控制
- REST API
业务逻辑要插哪里?再补一个 Spring Bean:
@Service
@RequiredArgsConstructor
public class CustomerDataProxy implements DataProxy<Customer> {
private final RiskClient risk;
@Override
public void beforeAdd(Customer model) {
if (risk.isBlacklisted(model.getName())) {
throw new EruptException("该客户在风控黑名单中");
}
}
}
数一下控制权落点:
🔹 字段是 Java 字段 → IDE 自动补全、重构、find usages 全部生效
🔹 校验逻辑在 beforeAdd → 直接挂 breakpoint,单测里 mock RiskClient 就能跑
🔹 风控调用走 @Autowired → 跟项目里其他 Spring 服务一个待遇,没有低代码 runtime 那种黑盒
最重要的一件事——所有这些代码,没有一行是框架生成的。
Customer.java 是你 IDE 里手敲的,CustomerDataProxy.java 也是。
Erupt 不向你的源码目录里写任何文件。
区别于 JeecgBoot / JNPF / RuoYi 的"画布生成代码"路径,Erupt 没有"生成"这个动词。
四、扩展点矩阵:每一类需求都有对应的 Spring Bean
后端工程师不是抵触"少写代码",是抵触"被迫离开我熟悉的扩展机制"。
Erupt 的扩展点全部以 Spring Bean / Java 接口的形式存在,没有"配置面板"那一层:
| 想做什么 | 实现接口 |
|---|---|
| 增删改查生命周期 | DataProxy<T> |
| 自定义查询过滤 | FilterHandler |
| 行级权限 | PowerHandler |
| 行级操作按钮 | OperationHandler |
| 下拉选项动态加载 | ChoiceFetchHandler / TagsFetchHandler |
| 输入联想 | AutoCompleteHandler |
| 类型安全查询 | eruptDao.lambdaQuery(...) |
注意,这张表里没有任何"在画布配 X"——全部是"实现 Y 接口"。
对一个写过 Java 的人,这一张表就是他原本熟悉的 Spring 接口注册模型。
抵触没有滋生的空间。
五、AI 能力:不是"装一个 ChatGPT 插件",而是默认到位
这是 Erupt 最被低估的部分。
国内低代码 + AI 几乎都是"加件"——
❌ 先有平台
❌ 再买 AI 模块
❌ 再配 LLM key
❌ 再单独学一遍它家的 Agent 配置 DSL
Erupt 把这一层做反了。
erupt-ai 跟 erupt-core 一样是默认依赖,引完 starter 之后整个 AI Harness 已经在那里:
erupt-ai/src/main/java/xyz/erupt/ai/llm/
├── ChatGpt.java Claude.java DeepSeek.java
├── Doubao.java Fireworks.java Gemini.java
├── GLM.java Grok.java MiniMax.java
├── Mimo.java Mistral.java Moonshot.java
├── Ollama.java OpenAIAdapter.java
├── OpenRouter.java Qwen.java Together.java
数一下:17 个 provider,全部在主仓,不是远端商店的插件。
接下来这件事才是真正的关键——
怎么把你自己的业务 Bean 暴露给 LLM 调用?
一行注解。
完整 @AiToolbox 注解定义,整整 12 行:
package xyz.erupt.annotation.ai;
import java.lang.annotation.*;
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@Documented
@Inherited
public @interface AiToolbox {
}
一个空标记注解。运行时被 AiToolboxManager 扫到——核心实现简单到看一眼就懂:
@Override
public void run(ApplicationArguments args) {
applicationContext.getBeansWithAnnotation(AiToolbox.class).values().forEach(bean -> {
Object target = AopProxyUtils.getSingletonTarget(bean);
Object realBean = target != null ? target : bean;
for (Method method : realBean.getClass().getDeclaredMethods()) {
if (method.isAnnotationPresent(Tool.class)) {
aiMethodMap.put(method.getName(), method);
aiMethodBeanMap.put(method.getName(), realBean);
}
}
});
}
启动时扫一遍带 @AiToolbox 的 Spring Bean,把里面带 @Tool 注解的方法登记进去。
就这样,你的业务 Bean 直接成了 LLM 工具。
写一个能让 AI 调用的 CRM 查询:
@AiToolbox
@Service
@RequiredArgsConstructor
public class CustomerAiTools {
private final EruptDao eruptDao;
@Tool("根据客户名模糊查询,返回前 20 条客户基本信息")
public List<Customer> searchCustomerByName(
@P("客户名关键字") String keyword) {
return eruptDao.lambdaQuery(Customer.class)
.like(Customer::getName, keyword)
.limit(20)
.list();
}
@Tool("把指定客户拉入风控黑名单")
public String blacklist(@P("客户 ID") Long customerId) {
Customer c = eruptDao.lambdaQuery(Customer.class)
.eq(Customer::getId, customerId).one();
if (c == null) return "客户不存在";
c.setLevel("BLACKLIST");
eruptDao.merge(c);
return "已拉黑:" + c.getName();
}
}
工程师视角看这段代码:100% 是普通 Spring Bean——@Service、构造注入、EruptDao lambda 查询。
多出来的只有 @AiToolbox 一个类注解和方法上的 @Tool。
下一次 LLM 收到用户消息"帮我查叫'张三'的客户",它自己就能调到 searchCustomerByName。
六、AI 能力全景对位
把 Erupt 现状摆出来跟国内对位:
| 能力 | Erupt 现状 | 国内对位 |
|---|---|---|
| LLM provider 数量 | 17 个内置 | 一般 1-3 个,扩展靠插件 |
| 多 Agent 协作(A2A) | 内置 | 几乎都要外接 LangGraph / Mastra |
| 跨会话 Memory | 内置 | 一般自己集成 Redis 方案 |
| MCP server | 内置 | 几乎没有原生支持 |
| Bean 暴露成 Tool | @AiToolbox 一行 | 通常需要写 schema JSON 注册 |
| 自治 Admin Agent | erupt-ai-claw 模块 | 一般是另购 |
erupt-ai-claw 单独说一句——
这是 Erupt 默认提供的自治 Admin Agent。
它知道当前后台有哪些 @Erupt 类、哪些字段、哪些行级操作,能直接代用户去查数据、改数据、跑系统操作。
所有权限受 LLMRoleService 的 RBAC 控制,不是放养。
七、跟 JeecgBoot Online Code / 钉钉宜搭 JS / 微搭 JS 怎么比
主流"拖拽 + 脚本派"的核心问题:你写的脚本和画布生成的代码之间永远在漂移。
把横向摆开:
| 维度 | JeecgBoot Online Code | 宜搭 JS / 微搭 JS | 简道云脚本 | Erupt |
|---|---|---|---|---|
| 业务逻辑在哪 | 平台在线 IDE | SaaS 表单事件 JS | 平台脚本编辑器 | 本机 IDE 的 Spring Bean |
| 调试 | 平台日志 | 浏览器 console | 平台日志 | 本机 IDE breakpoint |
| 单元测试 | 难(脚本不在仓库里) | 几乎不可能 | 几乎不可能 | JUnit + H2 |
| 复用 Spring 生态 | 部分 | ❌ | ❌ | 完全可用 |
| 包管理 | 平台内置 jar | 平台白名单 | 平台白名单 | pom.xml 任意依赖 |
| AI 工具暴露 | 需平台 AI 模块 | 需"低代码+AI"加件 | 需智能助手套件 | @AiToolbox 一行 |
| CI/CD | 应用包导出 | 应用包导入 | 应用包导入 | mvn package |
第一行最关键——
前三列都把开发者最熟悉的"业务逻辑"代码扣留在平台内部 IDE 或浏览器编辑器里。
Erupt 不扣留任何东西。
八、5 分钟,从零搭一个可控 + 带 AI 的后台
不是文章里画饼,是真的 5 分钟。
Step 1 - 新建 Spring Boot 项目,pom 加依赖:
<dependency>
<groupId>xyz.erupt</groupId>
<artifactId>erupt-web</artifactId>
<version>1.14.3</version>
</dependency>
<dependency>
<groupId>xyz.erupt</groupId>
<artifactId>erupt-ai</artifactId>
<version>1.14.3</version>
</dependency>
Step 2 - application.yml 配数据源(任意 JDBC 数据库都行):
spring:
datasource:
url: jdbc:h2:mem:erupt
driver-class-name: org.h2.Driver
jpa:
hibernate:
ddl-auto: update
Step 3 - 写一个 @Erupt 实体(前面 Customer 那段代码直接抄)。
Step 4 - mvn spring-boot:run,访问 http://localhost:8080
默认账号 erupt / erupt,登进去——
✅ 客户管理后台已经在那里
✅ AI 聊天框已经在那里
✅ 17 个 LLM provider 配置入口已经在那里
填一个 DeepSeek 的 API key,AI 就活了。
接着随手加一个:
@AiToolbox
@Service
public class MyTools {
@Tool("说当前时间")
public String now() { return LocalDateTime.now().toString(); }
}
重启,问 AI"现在几点"——
它会调你这个方法。
整个过程没有一步离开 IDE。
九、最后说一件事
我看到 Erupt 这套设计的时候,第一反应是——
"低代码"这三个字真的被国内市场绑死了。
绑死成"给业务运营用的拖拽工具",绑死成"给开发者添麻烦的代码生成器"。
很少有人讨论:能不能有一种低代码,做给后端工程师用,让他写的代码量降下来,但每一行的控制权一点都不丢?
Erupt 给的答案是肯定的。
它的衡量标准不是"业务零代码上线",而是——
"工程师写的代码量从 800 行降到 80 行,剩下 720 行的控制力一点没丢,外加默认装好一份 AI Harness。"
如果你写过 5 年以上 Java,被低代码这三个字伤过,值得看一眼。
🔗 想试试看?
📂 GitHub:github.com/erupts/erup…
📚 文档站:www.erupt.xyz