通用代码生成工具 - 基于 Velocity 模板引擎,支持从数据库表结构自动生成任何类型的文本文件。
📊 数据库表结构 + 📝 Velocity 模板 = 🚀 批量生成代码/配置/文档
一句话介绍:输入表结构,输出一切 —— Java、Vue、配置、文档、SQL 脚本,任何文本文件都能批量生成。
- ✅ Java 后端代码:Controller、Service、Repository、Entity、DTO、VO 等
- ✅ 前端代码:Vue 组件、React 组件、TypeScript 接口、API 层、Service 层等
- ✅ 配置文件:application.yml、数据库脚本、Docker 配置等
- ✅ 文档生成:API 文档、数据字典、Markdown 文档等
- ✅ 任意文本文件:只要是基于模板的文本内容,都可以生成
核心理念:你定义模板,我来批量生成。不限技术栈,不限文件类型。
与其他代码生成工具相比,Assembly Blueprint 的核心优势:
| 对比维度 | MyBatis Generator | JHipster | Assembly Blueprint |
|---|---|---|---|
| 生成范围 | 仅后端 Mapper/Entity | 全栈但固定技术栈 | ✅ 任意文件类型 |
| 技术栈 | 仅 MyBatis | 仅 Spring + Angular/React/Vue | ✅ 无限制,自定义模板 |
| 前端支持 | ❌ 不支持 | ✅ 支持但固定 | ✅ 支持且可定制 |
| 配置文件 | ❌ 不支持 | 部分支持 | ✅ 支持任意文本文件 |
| 文档生成 | ❌ 不支持 | ❌ 不支持 | ✅ 支持 Markdown/HTML 等 |
| 自定义模板 | 有限 | 困难 | ✅ 完全自由(Velocity) |
| 全局变量 | ❌ 不支持 | 有限 | ✅ 支持注入任意全局变量 |
| 调试能力 | 一般 | 一般 | ✅ projector.map.json 实时调试 |
- 无限制的文件生成:任何文本文件都能生成(Java、Vue、SQL、YAML、Markdown...)
- 灵活的数据采集:支持从 MySQL 数据库或自定义数据源采集表结构信息
- 标准化命名转换:自动将表名和字段名转换为 6 种命名格式(大驼峰、小驼峰、下划线、大写、小写等)
- Velocity 模板引擎:使用成熟的 Velocity 模板语法,学习成本低,功能强大
- 多技术栈支持:内置 Java JPA 和 Vue3 TypeScript 模板,可扩展任何技术栈 例如 Mybatis
- 全局变量支持:支持在所有模板中注入全局变量(如作者、版本、公司等)
- 调试友好:自动生成
projector.map.json文件,实时查看所有可用变量 - 批量生成:支持一次性为多张表生成完整的文件结构
- 智能覆盖控制:可配置文件覆盖策略,避免误覆盖已修改的文件
| 应用场景 | 输入 | 输出 | 效率提升 |
|---|---|---|---|
| 后端 CRUD 开发 | 数据库表结构 | Controller + Service + Repository + Entity + DTO/VO | 从 2 小时 → 2 分钟 |
| 前端页面开发 | 数据库表结构 | Vue 组件 + API 层 + Service 层 + TypeScript 接口 | 从 1 小时 → 1 分钟 |
| API 文档生成 | 数据库表结构 | Markdown 数据字典 | 从 30 分钟 → 10 秒 |
| 数据库脚本 | 数据库表结构 | INSERT 脚本、测试数据脚本 | 从 1 小时 → 30 秒 |
| 配置文件 | 数据库表结构 | application.yml、Docker 配置等 | 从 20 分钟 → 10 秒 |
投资回报率:一次编写模板,终身批量生成。100 张表的项目能节省数百小时开发时间。
Assembly Blueprint 采用标准的数据处理流水线架构:
数据采集 → 数据转换 → 模板投影 → 代码生成
Collector → Converter → Projector → Output
-
RawCollector(数据采集器)
MysqlCollector:从 MySQL 数据库采集表结构信息- 支持自定义实现采集其他数据源
-
PolyConverter(数据转换器)
MysqlToJavaPolyConverter:将 MySQL 类型转换为 Java 类型- 自动生成多种命名格式(驼峰、下划线等)
-
BlueprintCollector(蓝图采集器)
VelocityBlueprintCollector:扫描并加载 Velocity 模板文件
-
Projector(投影器)
VelocityProjector:使用 Velocity 引擎渲染模板并生成代码文件
-
AssemblyFactory(装配工厂)
- 统一的入口类,协调各组件完成代码生成流程
<dependency>
<groupId>com.ksptool</groupId>
<artifactId>assembly-blueprint</artifactId>
<version>2.2S-RC1</version>
</dependency>// 1. 创建 MySQL 采集器
MysqlCollector collector = new MysqlCollector();
collector.setUrl("jdbc:mysql://localhost:3306/your_database");
collector.setUsername("root");
collector.setPassword("password");
collector.setDatabase("your_database");
// 2. 创建蓝图采集器
VelocityBlueprintCollector blueprintCollector = new VelocityBlueprintCollector();
// 3. 创建转换器
PolyConverter converter = new MysqlToJavaPolyConverter();
// 4. 创建投影器
Projector projector = new VelocityProjector();
// 5. 创建工厂并配置
AssemblyFactory factory = new AssemblyFactory();
factory.setCollector(collector);
factory.setCollector(blueprintCollector);
factory.setConverter(converter);
factory.setProjector(projector);
// 6. 配置路径
factory.setInputBasePathFromRelative("blueprint_jpa"); // 模板目录
factory.setOutputBasePathFromRelative("output"); // 输出目录
// 7. 选择要生成的表
factory.selectTables("user", "role", "permission");
// 8. 配置选项
factory.removeTablePrefixes("t_", "sys_"); // 去除表名前缀
factory.removeFieldPrefixes("f_"); // 去除字段名前缀
factory.setOverwriteEnabled(true); // 允许覆盖已存在的文件
factory.enableProjectorMap(true); // 生成调试用的 map.json
// 9. 设置全局变量(可选)
factory.putGlobalVar("author", "张三");
factory.putGlobalVar("version", "1.0.0");
factory.putGlobalVar("company", "某某科技有限公司");
// 10. 执行生成
factory.execute();factory.setInputBasePathFromRelative("blueprint_jpa");
factory.selectTables("user", "role", "permission");
factory.execute();生成内容:
UserController.java- RESTful API 控制器UserService.java- 业务逻辑层UserRepository.java- JPA 数据访问层UserPo.java- JPA 实体类AddUserDto.java、EditUserDto.java、GetUserListDto.java- 数据传输对象GetUserListVo.java、GetUserDetailsVo.java- 视图对象
factory.setInputBasePathFromRelative("blueprint_vue");
factory.selectTables("user", "role", "permission");
factory.execute();生成内容:
User.vue- Vue 组件(包含查询表单、数据表格、新增/编辑对话框)UserApi.ts- TypeScript API 接口层(包含 5 个 DTO/VO 定义和 5 个接口方法)UserService.ts- 组合式函数(useUserList、useUserModal)
// 使用自定义模板目录
factory.setInputBasePathFromRelative("blueprint_config");
factory.selectTables("user", "order", "product");
factory.execute();示例模板:application-${ptalcn}.yml.vm
spring:
datasource:
url: jdbc:mysql://localhost:3306/${ptalcn}
username: root
password: root
jpa:
hibernate:
ddl-auto: update
properties:
hibernate:
format_sql: true
# 业务配置 - ${comment}
business:
module: ${ptalcn}
table: ${ptuln}
entity: ${ptstn}示例模板:数据字典-${ptstn}.md.vm
# ${comment}
**表名**:`${ptuln}`
## 字段说明
| 字段名 | 类型 | 必填 | 说明 |
|--------|------|------|------|
#foreach ($field in $fields)
| ${field.pfuln} | ${field.type} | #if(${field.required})是#{else}否#end | ${field.comment} |
#end
**生成时间**:${global.generateTime}
**生成人**:${global.author}示例模板:init-${ptuln}.sql.vm
-- ${comment}
-- 作者: ${global.author}
-- 版本: ${global.version}
INSERT INTO ${ptuln} (
#foreach ($field in $fields)
#if(!${field.primaryKey})
${field.pfuln}#if($foreach.hasNext),#end
#end
#end
) VALUES (
#foreach ($field in $fields)
#if(!${field.primaryKey})
''#if($foreach.hasNext),#end
#end
#end
);Assembly Blueprint 可以生成任何文本文件,包括但不限于:
| 文件类型 | 扩展名示例 | 用途 |
|---|---|---|
| Java | .java |
后端代码 |
| TypeScript/JavaScript | .ts, .js, .tsx, .jsx |
前端代码 |
| Vue/React | .vue, .jsx, .tsx |
前端组件 |
| 配置文件 | .yml, .yaml, .properties, .json, .xml |
应用配置 |
| 脚本 | .sql, .sh, .bat, .ps1 |
数据库脚本、Shell 脚本 |
| 文档 | .md, .txt, .html |
文档、说明 |
| Docker | Dockerfile, .dockerignore |
容器配置 |
| 其他 | 任意扩展名 | 只要是文本文件即可 |
关键:模板文件必须以
.vm结尾(如Controller.java.vm),生成时会自动去掉.vm后缀。
模板文件名支持占位符,会在生成时被替换:
#{PTSTN}- 表标准化名称(大驼峰)#{PTALCN}- 表全小写名称
命名示例:
| 模板文件名 | 生成文件名(表名:user_account) |
|---|---|
#{PTSTN}Controller.java.vm |
UserAccountController.java |
#{PTSTN}.vue.vm |
UserAccount.vue |
#{PTALCN}.config.yml.vm |
useraccount.config.yml |
README-#{PTSTN}.md.vm |
README-UserAccount.md |
init-#{PTULN}.sql.vm |
init-user_account.sql |
模板目录结构会被保留到输出目录:
blueprint_jpa/
└── src/main/java/com/ksptooi/biz/#{PTALCN}/
├── controller/
│ └── #{PTSTN}Controller.java.vm
├── service/
│ └── #{PTSTN}Service.java.vm
├── repository/
│ └── #{PTSTN}Repository.java.vm
└── model/
├── #{PTSTN}Po.java.vm
├── dto/
│ ├── Add#{PTSTN}Dto.java.vm
│ ├── Edit#{PTSTN}Dto.java.vm
│ └── Get#{PTSTN}ListDto.java.vm
└── vo/
├── Get#{PTSTN}ListVo.java.vm
└── Get#{PTSTN}DetailsVo.java.vm
| 变量名 | 说明 | 示例(表名:user_account) |
|---|---|---|
ptstn |
表标准化名称(大驼峰) | UserAccount |
ptscn |
表小驼峰名称 | userAccount |
ptbcn |
表大驼峰名称 | UserAccount |
ptuln |
表下划线名称 | user_account |
ptalcn |
表全小写名称 | useraccount |
ptaucn |
表全大写名称 | USERACCOUNT |
comment |
表注释 | 用户账户表 |
seq |
表序号 | 1 |
fields |
字段列表(数组) | [字段 1, 字段 2, ...] |
imports |
导入列表(数组) | [导入 1, 导入 2, ...] |
在 #foreach ($field in $fields) 循环中可用:
| 变量名 | 说明 | 示例(字段名:user_name) |
|---|---|---|
field.stdName |
字段标准化名称 | UserName |
field.pfstn |
字段标准化名称(大驼峰) | UserName |
field.pfscn |
字段小驼峰名称 | userName |
field.pfbcn |
字段大驼峰名称 | UserName |
field.pfuln |
字段下划线名称 | user_name |
field.pfalcn |
字段全小写名称 | username |
field.pfaucn |
字段全大写名称 | USERNAME |
field.type |
Java 类型 | String |
field.comment |
字段注释 | 用户名 |
field.required |
是否必填 | true/false |
field.primaryKey |
是否主键 | true/false |
field.seq |
字段序号 | 1 |
通过 factory.putGlobalVar(key, value) 设置的全局变量,可在所有模板中使用:
${global.author} ## 获取全局变量 author
${global.version} ## 获取全局变量 version
${global.company} ## 获取全局变量 companypackage com.ksptooi.biz.${ptalcn}.model;
import jakarta.persistence.*;
import lombok.Getter;
import lombok.Setter;
#foreach ($import in $imports)
import ${import};
#end
/**
* ${comment}
* @author ${global.author}
* @version ${global.version}
*/
@Getter
@Setter
@Entity
@Table(name = "${ptuln}")
public class ${ptstn}Po {
#foreach ($field in $fields)
#if(${field.primaryKey})
@Id
@Column(name = "${field.pfuln}"#if(${field.comment} != ''), comment = "${field.comment}"#end)
private ${field.type} ${field.pfscn};
#else
@Column(name = "${field.pfuln}"#if(!${field.required}), nullable = true#end#if(${field.comment} != ''), comment = "${field.comment}"#end)
private ${field.type} ${field.pfscn};
#end
#end
}启用 factory.enableProjectorMap(true) 后,会在输出目录生成 projector.map.json 文件,包含所有可用的模板变量,方便调试:
{
"ptstn": "User",
"ptscn": "user",
"ptbcn": "User",
"ptuln": "user",
"ptalcn": "user",
"ptaucn": "USER",
"comment": "用户表",
"seq": 1,
"fields": [
{
"stdName": "Id",
"pfstn": "Id",
"pfscn": "id",
"type": "Long",
"comment": "主键ID",
"required": true,
"primaryKey": true,
"seq": 1
}
],
"imports": ["java.time.LocalDateTime"],
"global": {
"author": "张三",
"version": "1.0.0"
}
}使用 SLF4J 日志框架,可通过配置日志级别查看详细的执行过程:
# logback.xml 或 slf4j 配置
com.ksptool.assembly.blueprint=DEBUG实现 RawCollector 接口:
public class CustomCollector implements RawCollector {
@Override
public List<RawTable> collect() {
// 实现自定义的数据采集逻辑
return tables;
}
@Override
public void select(String... tableNames) {
// 实现表选择逻辑
}
}实现 PolyConverter 接口:
public class CustomConverter implements PolyConverter {
@Override
public PolyTable toPolyTable(RawTable rawTable) {
// 实现自定义的类型转换逻辑
return polyTable;
}
@Override
public PolyBlueprint toPolyBlueprint(RawBlueprint rawBlueprint) {
// 实现蓝图转换逻辑
return polyBlueprint;
}
}- 表选择必须先配置:调用
execute()前必须先调用selectTables() - 路径配置顺序:
Projector手动设置的输出路径优先级高于AssemblyFactory的配置 - 文件覆盖控制:默认不覆盖已存在的文件,需要显式启用
setOverwriteEnabled(true) - 命名规范:模板文件必须以
.vm结尾才会被识别为 Velocity 模板 - 占位符使用:文件名和路径中的占位符格式为
#{PLACEHOLDER},区分大小写 - 文件类型无限制:可以生成任何扩展名的文本文件(
.java、.vue、.ts、.yml、.sql、.md等) - 技术栈无限制:不限于 Java 和 Vue,可以通过自定义模板支持任何技术栈
- 字符编码:生成的文件默认使用 UTF-8 编码
- Java 17+
- Apache Velocity 2.4.1 - 模板引擎
- MySQL Connector 9.5.0 - 数据库连接
- Apache Commons Lang3 3.20.0 - 工具库
- Lombok 1.18.42 - 代码简化
- Gson 2.13.2 - JSON 处理
- SLF4J 2.0.9 - 日志框架
- Spring Boot 3.x
- Spring Data JPA
- Jakarta Persistence API
- Lombok
- Vue 3.x
- TypeScript 5.x
- Element Plus
- Composition API
扩展性:你可以创建自己的模板目录,支持任何技术栈(React、Angular、Go、Python 等)
A: 可以!Assembly Blueprint 不限制生成的文件类型和语言。只要你编写对应的 Velocity 模板,就可以生成:
- 前端代码:Vue、React、Angular、TypeScript、JavaScript
- 后端代码:Java、Python、Go、Node.js、PHP
- 配置文件:YAML、JSON、XML、Properties
- 脚本文件:SQL、Shell、PowerShell
- 文档文件:Markdown、HTML、TXT
A: 可以!你可以:
- 实现自定义的
RawCollector接口,从其他数据库(PostgreSQL、Oracle、SQL Server)或数据源(Excel、JSON、API)采集数据 - 或者直接使用
RawCollector接口手动构造表结构数据
A: 取决于你的模板质量:
- 标准 CRUD 代码:模板设计良好时,可以做到开箱即用
- 复杂业务逻辑:建议生成基础代码框架后,手动添加业务逻辑
- 最佳实践:使用
setOverwriteEnabled(false)避免覆盖已修改的代码
A: 创建多个模板目录:
project/
├── blueprint_jpa/ # Java JPA 模板
├── blueprint_mybatis/ # MyBatis 模板
├── blueprint_vue/ # Vue 模板
├── blueprint_react/ # React 模板
└── blueprint_go/ # Go 模板
在代码中切换:
factory.setInputBasePathFromRelative("blueprint_vue"); // 使用 Vue 模板
// 或
factory.setInputBasePathFromRelative("blueprint_react"); // 使用 React 模板A: 可以!两种方式:
- 方式一:执行两次,分别指定不同的模板目录
- 方式二:创建一个包含前后端模板的混合目录
A: 可以!模板的目录结构会被保留到输出目录:
blueprint_jpa/src/main/java/... → output/src/main/java/...
你可以通过调整模板目录结构来控制输出结构。
A: 自定义 PolyConverter 实现,例如:
public class CustomConverter extends MysqlToJavaPolyConverter {
@Override
protected String convertType(String mysqlType) {
if (mysqlType.equals("JSON")) {
return "Map<String, Object>";
}
return super.convertType(mysqlType);
}
}A: 不难!Velocity 模板语法非常简单:
${变量名}- 输出变量#foreach($item in $list)...#end- 循环#if($condition)...#else...#end- 条件##- 注释
10 分钟即可上手,参考内置模板即可快速学习。
当前版本:2.2S-RC1
本项目为内部开发工具,版权归 KspTool 项目所有。