真正的低代码不在画布上,在你的 IDE 里

0 阅读9分钟

一个 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 / Cozeerupt-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-aierupt-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 Agenterupt-ai-claw 模块一般是另购

erupt-ai-claw 单独说一句——

这是 Erupt 默认提供的自治 Admin Agent

它知道当前后台有哪些 @Erupt 类、哪些字段、哪些行级操作,能直接代用户去查数据、改数据、跑系统操作。

所有权限受 LLMRoleService 的 RBAC 控制,不是放养。


七、跟 JeecgBoot Online Code / 钉钉宜搭 JS / 微搭 JS 怎么比

主流"拖拽 + 脚本派"的核心问题:你写的脚本和画布生成的代码之间永远在漂移

把横向摆开:

维度JeecgBoot Online Code宜搭 JS / 微搭 JS简道云脚本Erupt
业务逻辑在哪平台在线 IDESaaS 表单事件 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,被低代码这三个字伤过,值得看一眼


🔗 想试试看?

📂 GitHubgithub.com/erupts/erup…

📚 文档站www.erupt.xyz