# code-generator **Repository Path**: yuhanlu/code-generator ## Basic Information - **Project Name**: code-generator - **Description**: 基于关系型数据库和Freemarker的通用代码生成器 - **Primary Language**: Java - **License**: Apache-2.0 - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 2 - **Created**: 2023-05-08 - **Last Updated**: 2023-05-08 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # code-generator #### 背景 1. 在开发业务程序的时候,很多代码是模版化的,结构化的,这些代码用手敲或者用复制粘贴会很影响工作效率或者会出现一些莫名其妙的bug。如果使用自动生成模版代码的工具生成那些模版化的代码能够避免重复做无效的工作,提高工作效率 2. 在工作的这些年使用过很多自动生成代码的工具,最开始是Mybatis自带的工具,这个工具只能生成dao层和domain,不能够生成自定义的文件目录,自定义sql插件不够灵活。后来接触到一些使用模版文件自动生成代码的工具,但是这些模版有的一次只能生成一张表,有的生成文件目录结构不灵活,感觉不太合适 3. 在开发过程中,我们经历过的项目很多,每个项目都有不同的包结构,不同的代码规范和结构,就算是同一个工程中,不同的微服务间,甚至是同一个项目中不同的业务模块之间,因为经手的人太多、赶工期等各种原因,导致了包结构也有些差异,因此我想做一个通用的代码生成工具,最大限度的兼容各种项目的结构 4. 在参考了Git上大部分的代码生成工具之后,发现 [糖果代码生成器](https://gitee.com/turingoal/tg-common-generator.git) 的设计思路非常好,项目也很精简,因此基于这个款代码生成器进行了重构,把项目从Eclipse + Gradle改成了IDEA + Maven,并且结合了各个生成器的有点,提高了灵活性 #### 介绍 1. 本项目是一个通用代码生成工具,根据关系型数据库和Freemarker生成任何你想要的代码 2. 项目精简,项目通过Main方法生成代码,也可以打成jar包修改配置文件使用 3. 配置灵活,自己写的基于Json的配置文件功能,可以配置多个工程,可以指定要生成的表,可以同时生成多个项目和表,适用于多微服务开发的团队,建议提交保存配置文件团队之间共享 4. 灵活通用模版,模版的**文件路径**和**文件内容**都可以通过Freemarker标签替换,你只需要根据项目的实际情况定义项目的模版即可 5. 强调一下,灵活的配置文件,和灵活的模版方便你生成任何样子个性化代码,你可以生成任何开发语言后端、前端等模版化的代码 6. 后续考虑前端UI #### 目录结构 ``` . ├── pom.xml ├── src │ ├── main │ │ ├── java │ │ │ └── com │ │ │ └── gitee │ │ │ └── generator │ │ │ └── universal │ │ │ ├── CodeGenerator.java -- 生成代码逻辑 │ │ │ ├── Main.java -- Main方法,程序入口 │ │ │ ├── common -- 工具类 │ │ │ │ ├── Constants.java -- 常量 │ │ │ │ ├── DataTypeEnum.java -- 数据库->对象类型转换枚举工具类 │ │ │ │ ├── DefaultValArrayList.java -- 带默认值的List │ │ │ │ ├── FreeMarkerUtil.java -- FreeMarker工具类 │ │ │ │ ├── MethodUtil.java -- 方法工具类,在模版中通过${m.方法名()}调用 │ │ │ │ └── jsonconfig -- 基于json的配置文件工具类 │ │ │ │ ├── CreateByFastJson.java 基于FastJson的实现 │ │ │ │ └── JsonConfig.java 基于json的配置文件工具类 │ │ │ ├── datasource -- 数据源,查询数据库表信息 │ │ │ │ └── service │ │ │ │ ├── TableService.java │ │ │ │ └── impl │ │ │ │ └── TableServiceImpl.java │ │ │ └── domain -- 对应配置文件和模版中的数据属性 │ │ │ ├── GeneratorConfig.java -- 项目通用配置,总配置 │ │ │ ├── Project.java -- 继承GeneratorConfig,字段跟配置文件对应,在模版中通过${属性}取值 │ │ │ ├── Table.java -- 在模版中通过${table.属性}取值 │ │ │ └── TableColumn.java -- 在模版中通过${table.columns} 取到字段数组 │ │ └── resources 配置文件 │ │ ├── config-a.json -- 配置文件中的内容会合并到主配置文件里面,跟主配置文件是多对一的关系,这里暂时没有用 │ │ ├── config.json -- 主配置文件 │ │ ├── run.bat -- jar包运行项目批处理文件 │ │ ├── simplelogger.properties -- 日志配置文件 │ │ └── templates -- 模版默认存放目录 │ │ ├── jxpp -- 模版名称 │ │ └── jxpp-cms -- 模版名称 │ └── test └── target -- 项目编译、运行之后生成 ├── classes -- class文件路径 │ └── output -- 默认代码生成路径 │ ├── jxpp-cms -- 生成的项目代码 │ └── jxpp-tracking -- 生成的项目代码 └── code-generator -- maven packate 打包生成 ├── lib -- 项目依赖的jar包 ├── run.bat ├── simplelogger.properties ├── config-a.json ├── code-generator-1.0.jar -- 打包生成的可执行jar包 ├── config.json -- 若需要通过jar包运行,配置文件写在这里 ├── output -- 执行jar包后生成,默认的代码生成路径 │ ├── jxpp │ └── jxpp-cms └── templates -- 若需要通过jar包运行,模版写在这里 ├── jxpp └── jxpp-cms ``` #### 使用说明 1. 配置文件是一个Json对象,项目运行时会将 "generatorConfig" 属性解析成 GeneratorConfig 对象,GeneratorConfig对象包含Project对象信息,Project对象包含Table对象信息,Table对象包含TableColumn对象信息,所有对象中的属性都可以在模版中使用,包括模版的路径上 *(TableColumn中的属性要是在非要在文件路径上用的话,通过Freemarker中的方法也能也取值,不过没啥必要)* 2. 属性介绍 ###### GeneratorConfig: | 属性 | 取值 | 必填 | 默认值 | 解释 | |:----|:----|:----|:----|:----| | timeNow | ${timeNow} | 否 | 默认代码生成的时间 | 当前时间 | | templateBaseDir | ${templateBaseDir} | 否 | 默认值参考目录结构 | 模版文件夹所在的的绝对路径 | | outputBaseDir | ${outputBaseDir} | 否 | 默认值参考目录结构 | 生成代码文件夹所在的绝对路径 | ###### Project: | 属性 | 取值 | 必填 | 默认值 | 解释 | |:----|:----|:----|:----|:----| | projects | ${projects} | 是 | 无 | 项目名称,配置文件中 projects 对象的key | | templateName | ${templateName} | 是 | 无 | 需要指定代码的模版,即模版路径下的文件夹名称 | | basePackage | ${basePackage} | 是 | 无 | 项目的基础包名 | | datasourceUrl | ${datasourceUrl} | 是 | 无 | 数据库链接url | | datasourceUsername | ${datasourceUsername} | 是 | 无 | 数据库用户名 | | datasourcePassword | ${datasourcePassword} | 是 | 无 | 数据库密码 | | removePrefix | ${removePrefix} | 否 | 无 | 数组类型,要移除的表前缀,在配置文件中配置,生成代码时设置到每个Table里边,在模版中暂无取值的意义 | | generate | ${generate} | 否 | true | 是否生成本项目,程序运行时使用,在模版中暂无取值的意义 | ###### Table: | 属性 | 取值 | 必填 | 默认值 | 解释 | |:----|:----|:----|:----|:----| | tableName | ${table.tableName} | 是 | 无 | 表名,配置文件中 tables 对象的key,生成全部表的情况下从库中查询获得 | | | ${table.className} | 否 | 无 | 处理表名 table_name -> TableName | | | ${table.classNameFirstLower} | 否 | 无 | 处理表名 table_name -> tableName | | | ${table.underlineCaseName} | 否 | 无 | 处理表名 TableName -> table_name | | removePrefix | ${table.removePrefix} | 是 | 无 | 要移除的表前缀,Project中配置,在模版中暂无取值的意义 | | remarks | ${table.remarks} | 否 | 无 | 表的注释 | | columns | ${table.columns} | 否 | 无 | 查询数据库获取表的列list | | modelName | ${table.modelName} | 是 | 空字符串 | 模块名 | | modelNames | ${table.modelNames} | 是 | 无 | 业务模块名list,List为空,或者如果没有值,则使用modelName,为了兼容同一个表,在不同的层使用不同的模块名的问题 | | generate | ${table.generate} | 否 | true | 是否生成本表,程序运行时使用,在模版中暂无取值的意义 | ###### TableColumn: TableColumn中的属性从数据库中查询获得,${table.columns}取值获得TableColumn的集合,单独取值暂无意义,配合Freemarker遍历集合标签使用,例如: ``` <#list table.columns as column> /** ${column.remarks!} */ private ${column.fieldType} ${column.fieldNameFirstLower}; ``` | 属性 | 取值 | 必填 | 默认值 | 解释 | |:----|:----|:----|:----|:----| | tableName | ${column.tableName} | 是 | 无 | 表名,配置文件中 tables 对象的key,生成全部表的情况下从库中查询获得 | | columnName | ${column.columnName} | 是 | 无 | 数据库中的列名 | | | ${column.fieldName} | 否 | 无 | 处理列名 column_name -> ColumnName | | | ${column.fieldNameFirstLower} | 否 | 无 | 处理表名 column_name -> columnName | | | ${column.underlineCaseName} | 否 | 无 | 处理表名 ColumnName -> column_name | | remarks | ${column.remarks} | 否 | 无 | 库中列的注释 | | columnType | ${column.columnType} | 否 | 无 | 列类型 | | columnTypeName | ${column.columnTypeName} | 否 | 无 | 列类型名称例:VARCHAR | | | ${column.fieldType} | 否 | 无 | 数据库列类型转换为Java类型,关系在DataTypeEnum枚举中配置:VARCHAR -> String | | sortOrder | ${column.sortOrder} | 是 | 无 | 排序 | | size | ${column.size} | 否 | 无 | 大小或数据长度 | | isNullable | ${column.isNullable} | 否 | 无 | 是否为可空 | | autoIncrement | ${column.autoIncrement} | 否 | 无 | 是否为自增列 | | isPk | ${column.isPk} | 否 | 无 | 是否为主键 | ###### MethodUtil: 方法中都有非空判断 | 调用 | 解释 | |:----|:----| | ${m.toDir(table.modelName)} | "business.home" -> "business/home" | | ${m.prefixPoint(table.modelName)} | "business.home" -> ".business.home" |