代码基于SpringBoot3、Vue3、highlight实现自定义代码生成功能
SpringBoot3.x、MySQL8、MyBatisPlus3.5.x、velocity2.x、SpringSecurity6.x、Vue3、TypeScript、highlight
demo所需要的依赖及其对应版本号
pom
4.0.0 cn.molu mgzyf-api 2.4.1 Java 17 + SpringBoot3 + SpringSecurity6 org.springframework.boot spring-boot-starter-parent 3.1.5 17 17 UTF-8 5.8.15 8.0.28 1.2.16 3.5.3.1 1.5.3.Final 0.2.0 org.apache.velocity velocity-engine-core 2.3 org.projectlombok lombok provided org.projectlombok lombok-mapstruct-binding ${lombok-mapstruct-binding.version} provided cn.hutool hutool-all ${hutool.version} org.springframework.boot spring-boot-starter-web org.springframework.boot spring-boot-starter-security org.apache.commons commons-pool2 mysql mysql-connector-java ${mysql.version} com.alibaba druid-spring-boot-starter ${druid.version} com.alibaba fastjson 2.0.40 com.baomidou mybatis-plus-boot-starter ${mybatis-plus.version} org.springframework.boot spring-boot-starter-validation org.springframework.boot spring-boot-configuration-processor true ${project.artifactId} org.springframework.boot spring-boot-maven-plugin
这里是最基础的MySQL的配置信息
application
server:
port: 8989
spring:
jackson:
## 默认序列化时间格式
date-format: yyyy-MM-dd HH:mm:ss
## 默认序列化时区
time-zone: GMT+8
datasource:
type: com.alibaba.druid.pool.DruidDataSource
driver-class-name: com.mysql.cj.jdbc.Driver
druid:
master:
url: jdbc:mysql://127.0.0.1:3306/test01?zeroDateTimeBehavior=convertToNull&useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai&autoReconnect=true&allowMultiQueries=true
username: xxx
password: 123
driver-class-name: com.mysql.cj.jdbc.Driver
initial-size: 15
min-idle: 15
max-active: 200
max-wait: 60000
time-between-eviction-runs-millis: 60000
min-evictable-idle-time-millis: 300000
validation-query: ""
test-while-idle: true
test-on-borrow: false
test-on-return: false
pool-prepared-statements: false
connection-properties: false
# 配置生成代码的数据库
cn:
molu:
generate:
database: test01
这里是代码生成器的源码目录结构,下面会逐一展示这3个类

这里是根据我的项目需要,自定义的代码生成器模板,下面会以Service为例解释

提供数据到Vue页面的API接口,主要功能是将模板解析为代码返回给前台
import cn.molu.system.common.result.Result; import cn.molu.system.generate.mapper.ColumnDetailMapper; import cn.molu.system.generate.vo.ColumnDetailVo; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.apache.velocity.Template; import org.apache.velocity.VelocityContext; import org.apache.velocity.app.Velocity; import org.apache.velocity.exception.MethodInvocationException; import org.apache.velocity.exception.ParseErrorException; import org.apache.velocity.exception.ResourceNotFoundException; import org.springframework.beans.factory.annotation.Value; import org.springframework.cache.annotation.Cacheable; import org.springframework.web.bind.annotation.*; import java.io.IOException; import java.io.StringWriter; import java.util.List; import java.util.Map; import java.util.Properties; /** * @author 陌路 * @apiNote 数据库表细信息 * @date 2023/12/31 13:16 * @tool Created by IntelliJ IDEA */ @Slf4j @RestController @RequiredArgsConstructor @RequestMapping("/api/v1/gen") public class ColumnDetailController { @Value("${cn.molu.generate.database}") private String database; // 这里是数据库的名字,我的数据库是 test01 private final ColumnDetailMapper columnDetailMapper; /** * 获取所有表信息数据 * * @return List*/ @GetMapping("/getAllTables") @Cacheable(value = "gen:allTableDetails", key = "#root.methodName") public Result > getAllTables() { List
columnDetailVoList = columnDetailMapper.getColumnDetailMapVo(database); return Result.success(columnDetailVoList); } /** * 获取所有表中字段信息数据 * * @param tableName 表名 * @return List */ @GetMapping("/getTableInfo/{tableName}") public Result getTableInfo(@PathVariable String tableName, @RequestParam(value = "delPrefix", required = false) String delPrefix, @RequestParam(value = "packageName", required = false) String packageName, @RequestParam(value = "type") String type ) { List columnDetailVoList = columnDetailMapper.getColumnDetailMapVoByTableName(database, tableName); try (StringWriter writer = new StringWriter()) { // 初始化Velocity引擎 Properties p = new Properties(); // 加载classpath目录下的vm文件 p.setProperty("resource.loader.file.class", "org.apache.velocity.runtime.resource.loader.ClasspathResourceLoader"); // 定义字符集 p.setProperty(Velocity.INPUT_ENCODING, "UTF-8"); // 初始化Velocity引擎,指定配置Properties Velocity.init(p); // 获取模板 Template template = Velocity.getTemplate("vm/" + type + ".vm", "UTF-8"); ColumnDetailVo detailVo = new ColumnDetailVo(); Map map = detailVo.listToMap(columnDetailVoList, delPrefix); // 去除前缀 map.put("packageName", packageName); // 文件所在包 // 创建Velocity上下文 VelocityContext context = new VelocityContext(); // 设置模板中的变量 context.put("map", map); // 将模板与上下文数据进行合并 template.merge(context, writer); // 输出结果 String writerString = writer.toString(); return Result.success(writerString); } catch (IOException | ResourceNotFoundException | ParseErrorException | MethodInvocationException e) { log.error("报错了:" + e.getMessage(), e); } return Result.failed(); } }
查询数据库,获取表字段信息,以便后面生成代码使用
import cn.molu.system.generate.vo.ColumnDetailVo;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import java.util.List;
/**
* @author 陌路
* @apiNote 数据库表细信息
* @date 2023/12/31 13:14
* @tool Created by IntelliJ IDEA
*/
@Mapper
public interface ColumnDetailMapper {
/**
* 获取所有表信息数据
*
* @return List
*/
public List getColumnDetailMapVo(@Param("database") String database);
/**
* 获取所有表中字段信息数据
*
* @param tableName 表名
* @return List
*/
public List getColumnDetailMapVoByTableName(@Param("database") String database, @Param("tableName") String tableName);
}
根据application中指定的数据库名,获取数据库中所有的表名以及表中的字段名
对应表中字段和字段信息的实体类
import cn.hutool.core.date.DatePattern;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.StrUtil;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.fasterxml.jackson.annotation.JsonInclude;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;
import lombok.ToString;
import lombok.experimental.Accessors;
import org.springframework.format.annotation.DateTimeFormat;
import java.io.Serial;
import java.io.Serializable;
import java.util.*;
import java.util.concurrent.atomic.AtomicReference;
/**
* @author 陌路
* @apiNote 数据库表细信息
* @date 2023/12/31 13:21
* @tool Created by IntelliJ IDEA
*/
@Data
@ToString
@NoArgsConstructor
@EqualsAndHashCode
@Accessors(chain = true)
@JsonInclude(value = JsonInclude.Include.NON_NULL, content = JsonInclude.Include.NON_EMPTY)
public class ColumnDetailVo implements Serializable {
@Serial
private static final long serialVersionUID = 9196390045041955368L;
// ====================查询所有表信息====================
/**
* 表名
*/
private String tableName;
/**
* 表名注释
*/
private String tableComment;
/**
* 表数据引擎
*/
private String engine;
/**
* 表字符集
*/
private String tableCollation;
/**
* 表中数据条数
*/
private String tableRows;
/**
* 表创建时间
*/
@JsonFormat(pattern = "YYYY-MM-DD HH:mm:ss")
@DateTimeFormat(pattern = "YYYY-MM-DD HH:mm:ss")
private String createTime;
// ====================查询指定表中的字段信息====================
/**
* 数据库名
*/
private String tableSchema;
/**
* 字段名
*/
private String columnName;
/**
* 默认值
*/
private String columnDefault;
/**
* 是否可为空:YES、NO
*/
private String isNullable;
/**
* 数据类型:int、varchar...
*/
private String dataType;
/**
* 字段类型:int、varchar(30)...
*/
private String columnType;
/**
* 是否主键:PRI
*/
private String columnKey;
/**
* 是否自增:auto_increment(自增)
*/
private String extra;
/**
* 字段注释
*/
private String columnComment;
/**
* 是否主键
*
* @param columnKey 字段键
* @return 是否主键
*/
public boolean isPrimaryKey(String columnKey) {
return StrUtil.equalsIgnoreCase(columnKey, "PRI");
}
/**
* 获取主键字段名
*
* @param list 字段列表
* @return 主键字段名
*/
public String getPrimaryKey(List list) {
return Optional.ofNullable(list)
.orElseGet(ArrayList::new)
.stream()
.filter(item -> isPrimaryKey(item.columnKey))
.findFirst()
.orElseGet(ColumnDetailVo::new).columnName;
}
/**
* 列表转Map
*
* @param list 列表
* @param replacePrefix 替换前缀
* @return Map
*/
public Map listToMap(List list, String replacePrefix) {
if (Objects.isNull(list) || list.isEmpty()) return null;
Map map = new HashMap<>(2);
ColumnDetailVo detailVo = list.get(0);
String voTableName = detailVo.getTableName().toLowerCase();
String subTableName = voTableName.replace(replacePrefix, "");
String className = toUpperFirst(subTableName);
map.put("tableName", voTableName); // 表名
map.put("tableComment", detailVo.getTableComment()); // 表名注释
map.put("className", StrUtil.upperFirst(className)); // Java类名
map.put("subClassName", className); // Java类名
map.put("path", voTableName.replace("_", "/")); // 生成路径
map.put("prem", voTableName.replace("_", ":")); // 权限标识
map.put("currTime", DateUtil.format(new Date(), DatePattern.NORM_DATETIME_PATTERN)); // 日期时间
AtomicReference pk = new AtomicReference<>();
AtomicReference pkType = new AtomicReference<>();
AtomicReference getterPk = new AtomicReference<>();
AtomicReference pkColumn = new AtomicReference<>();
List
自定义的模板,通过模板生成所需要的代码
package $!{map.packageName}.service;
import $!{map.packageName}.entity.$!{map.className};
import com.baomidou.mybatisplus.core.metadata.IPage;
import $!{map.packageName}.params.$!{map.className}Params;
import java.lang.*;
/**
* @apiNote $!{map.tableComment}($!{map.className})表服务接口
* @author 陌路
* @date $!{map.currTime}
* @tool Created by IntelliJ IDEA
*/
public interface $!{map.className}Service /* extends IService<$!{map.className}> */{
/**
* 通过ID查询单条数据
*
* @author 陌路
* @date $!{map.currTime}
* @param $!{map.pk} 主键
* @return $!{map.subClassName} 实例对象
*/
$!{map.className} queryById($!{map.pkType} $!{map.pk});
/**
* 分页查询
*
* @author 陌路
* @date $!{map.currTime}
* @param $!{map.subClassName}Params 筛选条件
* @return IPage<$!{map.className}> 查询结果
*/
IPage<$!{map.className}> queryByPage($!{map.className}Params $!{map.subClassName}Params);
/**
* 新增数据
*
* @author 陌路
* @date $!{map.currTime}
* @param $!{map.subClassName} 实例对象
* @return $!{map.subClassName} 实例对象
*/
$!{map.className} insert($!{map.className} $!{map.subClassName}));
/**
* 修改数据
*
* @author 陌路
* @date $!{map.currTime}
* @param $!{map.subClassName} 实例对象
* @return $!{map.subClassName} 实例对象
*/
$!{map.className} update($!{map.className} $!{map.subClassName}));
/**
* 通过主键作废(逻辑删除)
*
* @author 陌路
* @date $!{map.currTime}
* @param ids 主键
* @return boolean 是否成功
*/
boolean deleteByIds(String ids);
/**
* 通过主键删除(物理删除)
*
* @author 陌路
* @date $!{map.currTime}
* @param ids 主键
* @return boolean 是否成功
*/
boolean removeByIds(String ids);
}
后台生成代码返回给vue页面,vue渲染,并使用语法高亮展示完整代码
搜索 重置 {{ scope.row.tableSchema }} {{ scope.row.tableName }} {{ scope.row.tableComment }} {{ scope.row.engine }} {{ scope.row.tableCollation }} {{ scope.row.tableRows }} {{ scope.row.createTime }} {{ scope.row.columnName }} {{ scope.row.columnDefault }} {{ scope.row.isNullable }} {{ scope.row.dataType }} {{ scope.row.columnType }} {{ scope.row.columnKey }} {{ scope.row.extra }} {{ scope.row.columnComment }} 预览 生成
1、选择需要生成代码的表
2、根据个人需求是否去除表前缀
3、生成的代码所在的包路径
点击生成即可生成代码,并可以直接复制使用

生成的菜单SQL语句,包含权限代码

可以生成vue3的语法支持的前端页面

可以生成我们需要的mapper.xml文件
里面包含对数据库的增删改查的语句

这里可以生成对Service的代码实现类

生成对外提供的接口层,包含所需要的权限,接口问道的doc解释等

以上就是使用SpringBoot3、JDK17、Vue3、SpringSecurity6等实现的代码生成器了,其他页面就不一一展示了
优点:
可扩展性高,可以根据自己不同的需求调整代码生成器以及生成逻辑
可自定义生成内容,支持范围广
可个自定义性化代码,按照自己喜欢的风格来自定义生成器