在选择的时候选择下述三个即可,springboot版本选择较低的即可
修改pom.xml中的依赖项目,便于大家直接cv,下述为所有需要的依赖,可以直接全选之后替换掉初始的pom.xml
4.0.0
org.springframework.boot
spring-boot-starter-parent
2.7.5
com.xiaoxin
boot
0.0.1-SNAPSHOT
XIAOXINCodeGeneratorDemo
XIAOXINCodeGeneratorDemo
8
3.5.2
1.33.0
org.springframework.boot
spring-boot-starter-web
com.mysql
mysql-connector-j
runtime
org.projectlombok
lombok
true
org.springframework.boot
spring-boot-starter-test
test
cn.hutool
hutool-all
5.8.10
org.apache.poi
poi-ooxml
5.2.3
com.baomidou
mybatis-plus-boot-starter-test
${mybatis-plus.vesion}
com.baomidou
mybatis-plus-generator
${mybatis-plus.vesion}
org.freemarker
freemarker
2.3.31
io.springfox
springfox-boot-starter
3.0.0
org.springframework.boot
spring-boot-starter-mail
org.springframework.boot
spring-boot-starter-data-redis
org.apache.commons
commons-pool2
net.reini
slf4-cdi
1.0
org.springframework.boot
spring-boot-starter-websocket
org.springframework.boot
spring-boot-maven-plugin
org.projectlombok
lombok
nexus-aliyun
nexus-aliyun
http://maven.aliyun.com/nexus/content/groups/public/
true
false
public
aliyun nexus
http://maven.aliyun.com/nexus/content/groups/public/
true
false
common,entity,mapper,service,controller,utils
server:
port: 9099
spring:
datasource:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://localhost:3306/test?serverTimezone=GMT%2b8
username: root
password: 123456
mvc:
pathmatch:
matching-strategy: ant_path_matcher
mybatis-plus:
mapper-locations: classpath:mapper/*.xml
configuration:
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
package ${package.Controller};
import cn.dev33.satoken.annotation.SaCheckPermission;
import cn.hutool.poi.excel.ExcelUtil;
import cn.hutool.poi.excel.ExcelReader;
import cn.hutool.poi.excel.ExcelWriter;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.ServletOutputStream;
import java.net.URLEncoder;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
import java.io.InputStream;
import java.util.List;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import ${package.Parent}.common.Result;
import org.springframework.web.multipart.MultipartFile;
import ${package.Service}.${table.serviceName};
import ${package.Entity}.${entity};
<#if restControllerStyle>
import org.springframework.web.bind.annotation.RestController;
<#else>
import org.springframework.stereotype.Controller;
<#if superControllerClassPackage??>
import ${superControllerClassPackage};
/**
*
* ${table.comment!} 前端控制器
*
*
* @author ${author}
* @since ${date}
*/
<#if restControllerStyle>
@RestController
<#else>
@Controller
@RequestMapping("<#if package.ModuleName?? && package.ModuleName != "">/${package.ModuleName}/<#if controllerMappingHyphenStyle>${controllerMappingHyphen}<#else>${table.entityPath}")
<#if kotlin>
class ${table.controllerName}<#if superControllerClass??> : ${superControllerClass}()
<#else>
<#if superControllerClass??>
public class ${table.controllerName} extends ${superControllerClass} {
<#else>
public class ${table.controllerName} {
@Resource
private ${table.serviceName} ${table.entityPath}Service;
@PostMapping
@SaCheckPermission("${table.entityPath}.add")
public Result save(@RequestBody ${entity} ${table.entityPath}) {
${table.entityPath}Service.save(${table.entityPath});
return Result.success();
}
@PutMapping
@SaCheckPermission("${table.entityPath}.edit")
public Result update(@RequestBody ${entity} ${table.entityPath}) {
${table.entityPath}Service.updateById(${table.entityPath});
return Result.success();
}
@DeleteMapping("/{id}")
@SaCheckPermission("${table.entityPath}.delete")
public Result delete(@PathVariable Integer id) {
${table.entityPath}Service.removeById(id);
return Result.success();
}
@PostMapping("/del/batch")
@SaCheckPermission("${table.entityPath}.deleteBatch")
public Result deleteBatch(@RequestBody List ids) {
${table.entityPath}Service.removeByIds(ids);
return Result.success();
}
@GetMapping
@SaCheckPermission("${table.entityPath}.list")
public Result findAll() {
return Result.success(${table.entityPath}Service.list());
}
@GetMapping("/{id}")
@SaCheckPermission("${table.entityPath}.list")
public Result findOne(@PathVariable Integer id) {
return Result.success(${table.entityPath}Service.getById(id));
}
@GetMapping("/page")
@SaCheckPermission("${table.entityPath}.list")
public Result findPage(@RequestParam(defaultValue = "") String name,
@RequestParam Integer pageNum,
@RequestParam Integer pageSize) {
QueryWrapper<${entity}> queryWrapper = new QueryWrapper<${entity}>().orderByDesc("id");
queryWrapper.like(!"".equals(name), "name", name);
return Result.success(${table.entityPath}Service.page(new Page<>(pageNum, pageSize), queryWrapper));
}
/**
* 导出接口
*/
@GetMapping("/export")
@SaCheckPermission("${table.entityPath}.export")
public void export(HttpServletResponse response) throws Exception {
// 从数据库查询出所有的数据
List<${entity}> list = ${table.entityPath}Service.list();
// 在内存操作,写出到浏览器
ExcelWriter writer = ExcelUtil.getWriter(true);
// 一次性写出list内的对象到excel,使用默认样式,强制输出标题
writer.write(list, true);
// 设置浏览器响应的格式
response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;charset=utf-8");
String fileName = URLEncoder.encode("${entity}信息表", "UTF-8");
response.setHeader("Content-Disposition", "attachment;filename=" + fileName + ".xlsx");
ServletOutputStream out = response.getOutputStream();
writer.flush(out, true);
out.close();
writer.close();
}
/**
* excel 导入
* @param file
* @throws Exception
*/
@PostMapping("/import")
@SaCheckPermission("${table.entityPath}.import")
public Result imp(MultipartFile file) throws Exception {
InputStream inputStream = file.getInputStream();
ExcelReader reader = ExcelUtil.getReader(inputStream);
// 通过 javabean的方式读取Excel内的对象,但是要求表头必须是英文,跟javabean的属性要对应起来
List<${entity}> list = reader.readAll(${entity}.class);
${table.entityPath}Service.saveBatch(list);
return Result.success();
}
}
package ${package.Entity};
<#list table.importPackages as pkg>
import ${pkg};
import cn.hutool.core.annotation.Alias;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import com.partner.boot.common.LDTConfig;
<#if entityLombokModel>
import lombok.Getter;
import lombok.Setter;
<#if chainModel>
import lombok.experimental.Accessors;
/**
private static final long serialVersionUID = 1L;
<#-- ---------- BEGIN 字段循环遍历 ---------->
<#list table.fields as field>
<#if field.keyFlag>
<#assign keyPropertyName=“${field.propertyName}”/>
<#if field.comment!?length gt 0>
<#if swagger>
// ${field.comment}
@ApiModelProperty("${field.comment}")
@Alias("${field.comment}")
<#if field.keyFlag>
<#-- 主键 -->
<#if field.keyIdentityFlag>
@TableId(value = "${field.annotationColumnName}", type = IdType.AUTO)
<#elseif idType??>
@TableId(value = "${field.annotationColumnName}", type = IdType.${idType})
<#elseif field.convert>
@TableId("${field.annotationColumnName}")
<#-- 普通字段 -->
<#elseif field.fill??>
<#-- ----- 存在字段填充设置 ----->
<#if field.convert>
@TableField(value = "${field.annotationColumnName}", fill = FieldFill.${field.fill})
<#else>
@TableField(fill = FieldFill.${field.fill})
@JsonDeserialize(using = LDTConfig.CmzLdtDeSerializer.class)
@JsonSerialize(using = LDTConfig.CmzLdtSerializer.class)
<#elseif field.convert>
@TableField("${field.annotationColumnName}")
<#-- 乐观锁注解 -->
<#if field.versionField>
@Version
<#-- 逻辑删除注解 -->
<#if field.logicDeleteField>
@TableLogic(value = “0”, delval = “id”)
private ${field.propertyType} ${field.propertyName};
<#------------ END 字段循环遍历 ---------->
<#if !entityLombokModel>
<#list table.fields as field>
<#if field.propertyType == “boolean”>
<#assign getprefix=“is”/>
<#else>
<#assign getprefix=“get”/>
public ${field.propertyType} ${getprefix}${field.capitalName}() {
return ${field.propertyName};
}
<#if chainModel>
public ${entity} set${field.capitalName}(${field.propertyType} ${field.propertyName}) {
<#else>
public void set${field.capitalName}(${field.propertyType} ${field.propertyName}) {
this.${field.propertyName} = ${field.propertyName};
<#if chainModel>
return this;
}
<#if entityColumnConstant>
<#list table.fields as field>
public static final String ${field.name?upper_case} = "${field.name}";
<#if activeRecord>
@Override
public Serializable pkVal() {
<#if keyPropertyName??>
return this.${keyPropertyName};
<#else>
return null;
}
<#if !entityLombokModel>
@Override
public String toString() {
return "${entity}{" +
<#list table.fields as field>
<#if field_index==0>
"${field.propertyName} = " + ${field.propertyName} +
<#else>
", ${field.propertyName} = " + ${field.propertyName} +
"}";
}
}
package com.xiaoxin.codegeneratordemo.common;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.io.Serializable;
/**
* xiaoxin
* 接口统一返回包装类
*/
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Result implements Serializable {
private static final long serialVersionUID = 42L;
private static final String CODE_SUCCESS = "200";
private static final String CODE_SYS_ERROR = "500";
private String code;
private String msg;
private Object data;
public static Result success() {
return new Result(CODE_SUCCESS, "操作成功", null);
}
public static Result success(Object data) {
return new Result(CODE_SUCCESS, "操作成功", data);
}
public static Result error(String code, String msg) {
return new Result(code, msg, null);
}
public static Result error(String msg) {
return new Result(CODE_SYS_ERROR, msg, null);
}
public static Result error() {
return new Result(CODE_SYS_ERROR, "系统错误", null);
}
}
package com.xiaoxin.datinghubback.utils;
import lombok.Builder;
import lombok.Data;
@Data
@Builder
public class DBProp {
private String url;
private String username;
private String password;
}
package com.xiaoxin.datinghubback.utils;
import lombok.Builder;
import lombok.Data;
@Data
@Builder
public class TableColumn {
private String columnName;
private String dataType;
private String columnComment;
}
下述代码中我们一般只需要修改表名,作者名,包名即可
package com.xiaoxin.codegeneratordemo.utils;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.io.resource.ResourceUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.db.Db;
import cn.hutool.db.DbUtil;
import cn.hutool.db.Entity;
import cn.hutool.db.ds.simple.SimpleDataSource;
import com.baomidou.mybatisplus.annotation.FieldFill;
import com.baomidou.mybatisplus.generator.FastAutoGenerator;
import com.baomidou.mybatisplus.generator.config.OutputFile;
import com.baomidou.mybatisplus.generator.engine.FreemarkerTemplateEngine;
import com.baomidou.mybatisplus.generator.fill.Column;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.config.YamlPropertiesFactoryBean;
import org.springframework.core.io.ClassPathResource;
import javax.sql.DataSource;
import java.sql.SQLException;
import java.util.*;
/**
* 代码生成器
* v1.0
* 作者:xiaoxin
*/
@Slf4j
public class CodeGenerator {
private static final String TABLE = "dynamic"; // 表名
private static final String MODULE_NAME = "动态"; // 菜单名称
private static final String PACKAGE_NAME = "com.xiaoxin.datinghubback"; // java代码的包名
private static final String AUTHOR = "xiaoxin"; // 作者
//
// private static final String VUE_CODE_PATH = ""; // vue代码的路径
/*========================= 下面的不用改动 =========================*/
private static final String PROJECT_PATH = System.getProperty("user.dir");
public static final String MAPPER_XML_PATH = "/src/main/resources/mapper/";
public static final String JAVA_CODE_PATH = "/src/main/java/";
private static final String SPACE6 = " ";
private static final String SPACE8 = " ";
private static final String SPACE10 = " ";
private static final String SPACE4 = " ";
public static void main(String[] args) throws SQLException {
generateJava(TABLE); // 生成Java后台代码
// generateVue(TABLE); // 生成Vue文件
// generatePermissionSqlData(TABLE); // 生成权限菜单
}
private static void generatePermissionSqlData(String tableName) throws SQLException {
// 获取数据库连接的信息
DBProp dbProp = getDBProp();
// 连接数据库
DataSource dataSource = new SimpleDataSource(dbProp.getUrl(), dbProp.getUsername(), dbProp.getPassword());
Db db = DbUtil.use(dataSource);
String lowerEntity = getLowerEntity(tableName);
// 先删除菜单sql再插入新的sql
db.execute("delete from `sys_permission` where `auth` like '" + lowerEntity + "%' or path like '" + lowerEntity + "%'");
db.execute("INSERT INTO `sys_permission` (`name`, `path`, `icon`, `page`, `type`) " +
"VALUES (?, ?, ?, ?, ? )", MODULE_NAME + "管理", lowerEntity, "grid",
getEntity(tableName), "2");
List pages = db.findBy("sys_permission", "path", lowerEntity);
Entity entity = pages.get(0);
Integer pid = entity.getInt("id");
db.execute("INSERT INTO `sys_permission` (`name`, `auth`, `pid`, `type`) " +
"VALUES (?, ?, ?, ?)", MODULE_NAME + "查询", lowerEntity + ".list", pid, "3");
db.execute("INSERT INTO `sys_permission` (`name`, `auth`, `pid`, `type`) " +
"VALUES (?, ?, ?, ?)", MODULE_NAME + "新增", lowerEntity + ".add", pid, "3");
db.execute("INSERT INTO `sys_permission` (`name`, `auth`, `pid`, `type`) " +
"VALUES (?, ?, ?, ?)", MODULE_NAME + "导入", lowerEntity + ".import", pid, "3");
db.execute("INSERT INTO `sys_permission` (`name`, `auth`, `pid`, `type`) " +
"VALUES (?, ?, ?, ?)", MODULE_NAME + "导出", lowerEntity + ".export", pid, "3");
db.execute("INSERT INTO `sys_permission` (`name`, `auth`, `pid`, `type`) " +
"VALUES (?, ?, ?, ?)", "批量删除", lowerEntity + ".deleteBatch", pid, "3");
db.execute("INSERT INTO `sys_permission` (`name`, `auth`, `pid`, `type`) " +
"VALUES (?, ?, ?, ?)", MODULE_NAME + "编辑", lowerEntity + ".edit", pid, "3");
db.execute("INSERT INTO `sys_permission` (`name`, `auth`, `pid`, `type`) " +
"VALUES (?, ?, ?, ?)", MODULE_NAME + "删除", lowerEntity + ".delete", pid, "3");
// 给管理员默认所有的权限
List adminRole = db.findBy("sys_role", "flag", "ADMIN");
if (CollUtil.isNotEmpty(adminRole)) {
// 先删除管理员权限
db.execute("delete from `sys_role_permission` where `role_id` = " + adminRole.get(0).getInt("id"));
List permissionAll = db.findAll("sys_permission");
// 再添加所有权限给管理员
for (Entity per : permissionAll) {
db.execute("INSERT INTO `sys_role_permission` (`role_id`, `permission_id`) " +
"VALUES (?, ?)", adminRole.get(0).getInt("id"), per.getInt("id"));
}
}
log.debug("========================== 菜单Sql生成完成!!!==========================");
}
private static void generateVue(String tableName) {
List tableColumns = getTableColumns(tableName);
// 读取模板,生成代码
String vueTemplate = ResourceUtil.readUtf8Str("templates/vue.template");
// 封装模板的代码
Map map = new HashMap<>();
map.put("lowerEntity", getLowerEntity(tableName)); // 接口前缀
String vueTableBody = getVueTableBody(tableColumns);
map.put("tableBody", vueTableBody);
String vueFormBody = getVueFormBody(tableColumns);
map.put("formBody", vueFormBody);
map.put("moduleName", MODULE_NAME);
// 生成页面代码
// String vuePage = StrUtil.format(vueTemplate, map); // vuePage是替换字符串模板后的内容
// 写文件
// "D:\\知识星球\\partner-manager\\src\\views\\" 是你vue工程文件的目录
String entity = getEntity(tableName);
// FileUtil.writeUtf8String(vuePage, VUE_CODE_PATH + entity + ".vue");
log.debug("==========================" + entity + ".vue文件生成完成!!!==========================");
}
private static List getTableColumns(String tableName) {
// 获取数据库连接的信息
DBProp dbProp = getDBProp();
// 连接数据库
DataSource dataSource = new SimpleDataSource("jdbc:mysql://localhost:3306/information_schema", dbProp.getUsername(), dbProp.getPassword());
Db db = DbUtil.use(dataSource);
// 拿到实际要生成代码的数据库的名称
String url = dbProp.getUrl();
String schema = url.substring(url.indexOf("3306/") + 5, url.indexOf("?"));
List tableColumnList = new ArrayList<>();
try {
List columns = db.findAll(Entity.create("COLUMNS").set("TABLE_SCHEMA", schema).set("TABLE_NAME", tableName));
//封装结构化的表数据信息
for (Entity entity : columns) {
String columnName = entity.getStr("COLUMN_NAME"); // 字段名称
String dataType = entity.getStr("DATA_TYPE"); // 字段名称
String columnComment = entity.getStr("COLUMN_COMMENT"); // 字段名称
TableColumn tableColumn = TableColumn.builder().columnName(columnName).dataType(dataType).columnComment(columnComment).build();
tableColumnList.add(tableColumn);
}
} catch (SQLException e) {
throw new RuntimeException(e);
}
return tableColumnList;
}
private static String getVueTableBody(List tableColumnList) {
StringBuilder builder = new StringBuilder();
for (TableColumn tableColumn : tableColumnList) {
if (tableColumn.getColumnName().equalsIgnoreCase("id") && StrUtil.isBlank(tableColumn.getColumnComment())) {
tableColumn.setColumnComment("编号");
}
if (tableColumn.getColumnName().equalsIgnoreCase("deleted") || tableColumn.getColumnName().equalsIgnoreCase("create_time")
|| tableColumn.getColumnName().equalsIgnoreCase("update_time")) { // 排除deleted create_time update_time 这个无需关注的字段
continue;
}
String camelCaseName = StrUtil.toCamelCase(tableColumn.getColumnName());
if (tableColumn.getColumnName().endsWith("img")) {
builder.append(SPACE6).append(" \n");
} else if (tableColumn.getColumnName().endsWith("file")) {
builder.append(SPACE6).append(" 点击下载 \n");
} else {
builder.append(SPACE6).append(" \n");
}
}
return builder.toString();
}
private static String getVueFormBody(List tableColumnList) {
StringBuilder builder = new StringBuilder();
for (TableColumn tableColumn : tableColumnList) {
if (tableColumn.getColumnName().equalsIgnoreCase("id")) {
continue;
}
if (tableColumn.getColumnName().equalsIgnoreCase("deleted") || tableColumn.getColumnName().equalsIgnoreCase("create_time")
|| tableColumn.getColumnName().equalsIgnoreCase("update_time")) { // 排除deleted create_time update_time 这个无需关注的字段
continue;
}
String camelCaseName = StrUtil.toCamelCase(tableColumn.getColumnName());
builder.append(SPACE8).append("\n");
if (tableColumn.getColumnName().contains("time")) {
// 日期时间
builder.append(SPACE10).append(" \n");
} else if (tableColumn.getColumnName().endsWith("date")) {
// 日期
builder.append(SPACE10).append(" \n");
} else if (tableColumn.getColumnName().endsWith("file")) {
// 文件上传
builder.append(SPACE10).append("\n");
builder.append(SPACE10).append(" 点击上传 \n");
builder.append(SPACE10).append(" \n");
} else if (tableColumn.getColumnName().endsWith("img")) {
// 文件上传
builder.append(SPACE10).append("\n");
builder.append(SPACE10).append(" 点击上传 \n");
builder.append(SPACE10).append(" \n");
} else {
builder.append(SPACE10).append(" \n");
}
builder.append(SPACE8).append(" \n");
}
return builder.toString();
}
private static String getLowerEntity(String tableName) {
tableName = tableName.replaceAll("t_", "").replaceAll("sys_", "");
return StrUtil.toCamelCase(tableName);
}
private static String getEntity(String tableName) {
String lowerEntity = getLowerEntity(tableName);
return lowerEntity.substring(0, 1).toUpperCase() + lowerEntity.substring(1);
}
private static DBProp getDBProp() {
ClassPathResource resource = new ClassPathResource("application.yml");
YamlPropertiesFactoryBean yamlPropertiesFactoryBean = new YamlPropertiesFactoryBean();
yamlPropertiesFactoryBean.setResources(resource);
Properties dbProp = yamlPropertiesFactoryBean.getObject();
return DBProp.builder().url(dbProp.getProperty("spring.datasource.url"))
.username(dbProp.getProperty("spring.datasource.username"))
.password(dbProp.getProperty("spring.datasource.password")).build();
}
private static void generateJava(String tableName) {
DBProp dbProp = getDBProp();
FastAutoGenerator.create(dbProp.getUrl(), dbProp.getUsername(), dbProp.getPassword())
.globalConfig(builder -> {
builder.author(AUTHOR) // 设置作者
.enableSwagger()
.disableOpenDir()
.outputDir(PROJECT_PATH + JAVA_CODE_PATH); // 指定输出目录
})
.packageConfig(builder -> {
builder.parent(PACKAGE_NAME) // 设置父包名
.moduleName("") // 设置父包模块名
.pathInfo(Collections.singletonMap(OutputFile.xml, PROJECT_PATH + MAPPER_XML_PATH)); // 设置mapperXml生成路径
})
.strategyConfig(builder -> {
builder.controllerBuilder().fileOverride().enableRestStyle().enableHyphenStyle()
.serviceBuilder().fileOverride()
.mapperBuilder().fileOverride()
.entityBuilder().fileOverride().enableLombok()
.logicDeleteColumnName("deleted")
.addTableFills(new Column("create_time", FieldFill.INSERT))
.addTableFills(new Column("update_time", FieldFill.INSERT_UPDATE));
builder.addInclude(tableName) // 设置需要生成的表名
.addTablePrefix("t_", "sys_"); // 设置过滤表前缀
})
.templateEngine(new FreemarkerTemplateEngine()) // 使用Freemarker引擎模板,默认的是Velocity引擎模板
.execute();
}
}
找到启动类,直接运行
便于接口测试,在navacat中直接数据生成
随便生成50条数据
随机生成五十条数据
访问localhost:9099/user,访问其中一个接口来测试