java工具:支持自定义代码生成工具

K-Code-Generator是一个用于自定义代码生成的工具,它读取数据库表结构,利用Velocity模板语言生成Java源代码。用户可以通过配置文件定制模板,支持Swagger功能,以及使用snippets进行代码抽象。该工具支持Gradle和Maven集成,提供灵活的数据库配置和模板策略。
摘要由CSDN通过智能技术生成

项目地址

https://github.com/kylin-hunter/k-commons/tree/main/k-code-generator



前言

一个基于数据库的自定义代码生成工具


一、架构

通过读取数据库的表结构信息,利用velocity自动生成源代码。

在这里插入图片描述

二、使用步骤

1 引入库

1.1 编译并发布到本地

        gradle clean build publishToMavenLocal-x test

1.2 gradle (gradle.org)


         implementation 'io.github.kylin-hunter:k-code-generator:1.0.4'

1.3 maven (maven.apache.org)


        <dependency>
          <groupId>io.github.kylin-hunter</groupId>
          <artifactId>k-code-generator</artifactId>
          <version>1.0.4</version>
        </dependency>

2 使用说明

2.1 创建一个表 test_user


CREATE TABLE IF NOT EXISTS `k_junit_code_role`
(
    `id`   bigint(20)  NOT NULL COMMENT 'primary unique id' AUTO_INCREMENT,
    `name` varchar(64) NOT NULL DEFAULT '' COMMENT 'role name',
    PRIMARY KEY (`id`)
) comment =' the roles';

CREATE TABLE IF NOT EXISTS `k_junit_code_user`
(
    `id`                  bigint(20)     NOT NULL COMMENT 'primary unique id' AUTO_INCREMENT,
    `name`                varchar(64)    NOT NULL DEFAULT '' COMMENT 'user name ',
    `birth`               datetime       NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT 'birthday',
    `leave_company_time`  timestamp      NOT NULL COMMENT 'the time leave company',
    `join_company_date`   date           NOT NULL COMMENT 'what time to join the company',
    `work_time`           time           NOT NULL COMMENT 'what time to work ervery moring',
    `work_hours`          int            NOT NULL DEFAULT 0 COMMENT 'how many hours to work everyday',
    `age`                 smallint       NOT NULL DEFAULT 0 COMMENT 'age',
    `height`              float(9, 2)    NOT NULL DEFAULT 0 COMMENT 'height',
    `weight`              double(19, 2)  NOT NULL DEFAULT 0 COMMENT 'weight',
    `money_income`        decimal(20, 2) NOT NULL DEFAULT 0 COMMENT 'all money income',
    `money_spend`         decimal(19, 0) NOT NULL DEFAULT 0 COMMENT 'the money spent',
    `address`             varchar(512)   NOT NULL DEFAULT 0 COMMENT 'address',
    `delete_flag`         tinyint(1)     NOT NULL DEFAULT 0 COMMENT 'is deleted',
    `sex`                 tinyint(2)     NOT NULL DEFAULT 0 COMMENT '0 unkown 1 male 2 female',
    `role_id`             bigint(20)     NOT NULL DEFAULT 0 COMMENT '角色 ID',
    `extend_1`            varchar(256)   NOT NULL DEFAULT 0 COMMENT '预留字段1',
    `extend_2`            varchar(256)   NOT NULL DEFAULT 0 COMMENT '预留字段2',
    `extend_3`            varchar(256)   NOT NULL DEFAULT 0 COMMENT '预留字段3',
    PRIMARY KEY (`id`),
    constraint test_user_role_fk
   foreign key (role_id) references k_junit_code_role (id)
) comment ='the user';


2.2 创建数据库配置文件k-db-config.yaml (放到classpath下)

此配置文件主要用以读取数据库的表信息


datasources:
  - driverClassName: 'com.mysql.cj.jdbc.Driver'
    url: 'jdbc:mysql://localhost:3306/kp?useUnicode=true&characterEncoding=utf8&useSSL=false&allowPublicKeyRetrieval=true&allowMultiQueries=true&serverTimezone=Asia/Shanghai'
    username: 'root'
    password: 'root'
    pool:
      minimumIdle: 1
      maximumPoolSize: 10
      connectionTimeout: 30000 # default 30000
      idleTimeout: 600000 # default: 600000 (10 minutes)
      maxLifetime: 1800000  # default: 1800000 (30 minutes
      validationTimeout: 5000 # default: 5000
    properties:
      cachePrepStmts: true
      prepStmtCacheSize: 250
      prepStmtCacheSqlLimit: 2048

2.3 创建模板的配置文件 k-generator-config.yaml (放到classpath下)

参考:https://github.com/kylin-hunter/k-commons/blob/main/k-code-generator/src/test/resources/k-generator-config.yaml
下面是模板配置文件的一些重要注释

global: # 全局配置
  template_path: '/User/bijian/template'   # 模板所在目录,可以使用当前目录, 例如 $user.dir$/templates
  output:
    path: '/User/bijian/output'    #   生成的源码所在目录,可以使用当前目录, 例如 $user.dir$/output
    #  output_path: '/Users/bijian/workspace_gitee/k-commons/k-generator/output'
    auto_clean: true # 自动清理上一次生成结果
    auto_create: true # 如果目录不存在自动生成输出目录       
modules:
  database:
    name: "kp"
    sql_types: # 支持一些自定义的sql类型映射(可选)
      "datetime": "java.time.LocalTime"  # 自定义:datetime类型, 映射为 java.time.LocalTime
      "smallint": "java.lang.Short"  # 自定义: smallint 类型, 映射为 java.lang.Short
      "(type=='decimal' && size<=19 && precision==0)": "java.lang.Long"
      # decimal(size<=19,precision==0), 会被映射为 java.lang.Long 例如 decimal(10,0) 就会被映射为  java.lang.Long  
  list:
    - name: 'User' # 模块的名字
      context:
        'module_custom_propery': 'module_custom_propery_value'  # 自定义一个模板的变量
      table:
        name: "k_junit_code_user" #表名
        skip_columns: #  屏蔽某些表的列
          - 'delete_flag'
          - 'extend_1'
          - 'extend_2'
          - 'extend_3'
        column_types: # 支持自定义 column 的映射类型(可选)
          "role_id": "java.lang.Integer"  # role_id 列 被映射为 java.lang.Integer
    - name: 'Role' # 支持定义多个模块,这是第二个模块
      table:
        name: 'k_junit_code_role'
templates: # 模板定义
  context:
    'author': 'bijian'  # 模板的全局变量  定一个作者 
  strategy: # 
    template_encoding: UTF-8 # 模板编码
    output_encoding: UTF-8 # 生成的源代码编码
  list:
    - name: basic.vm  #定义一个模板 basic.vm
      enabled: true
      context:
        'basic_vm_custom_property': 'basic_vm_custom_property_value'  #  模板的自定义变量
      strategy:
        package_name: '"com.kylinhunter."+k.str_lower(module.name)' #根据模块名字定义包名
        class_name: k.str_camel(module.name,'upper')+'Basic' #根据模块的名字定义类名
        super_class: 'java.util.ArrayList' # 父类
        interfaces:  # 接口
          - java.io.Serializable
          - java.lang.Cloneable
        extension: 'java' # 生成文件的扩展名
    - name: basic_swagger.vm #定义第二个模板 basic_swagger.vm
      enabled: true
      context:
        'basic_swagger_vm_custom_property': 'basic_swagger_vm_custom_property_value'  # 模板的自定义变量
      strategy:
        package_name: '"com.kylinhunter."+k.str_lower(module.name)' #根据模块名字定义包名
        class_name: k.str_camel(module.name,'upper')+'BasicSwagger' #根据模块的名字定义类名
        super_class: 'java.util.ArrayList'  # 父类
        interfaces: # 接口
          - java.io.Serializable
          - java.lang.Cloneable
        extension: 'java'  # 生成文件的扩展名
    - name: basic_swagger_snippet.vm
      enabled: true
      context:
        'basic_swagger_snippet_vm_custom_property': 'basic_swagger_snippet_vm_custom_property_value'  # 模板的自定义变量
      strategy:
        package_name: '"com.kylinhunter."+k.str_lower(module.name)' #根据模块名字定义包名
        class_name: k.str_camel(module.name,'upper')+'BasicSwaggerSnippet' #根据模块的名字定义类名
        super_class: 'java.util.ArrayList'  # 父类
        interfaces:# 接口
          - java.io.Serializable
          - java.lang.Cloneable
        extension: 'java'  # 生成文件的扩展名

2.4. 模板语法介绍和使用

模板的语法参考volecity的语法

2.4.1 基本使用
基本示例释义
${class.packageName}输出包名
${class.name}输出类名
${class.imports(“import “,”;”)}输出所有的引用包, 'import '开头 ;结尾,自动回车,简写为${class.imports}
$!{class.comment}类的注释,默认为数据库表的注释
${class.superClass("extends ")}输出父类, extends开头 ,简写为 ${class.superClass}
${class.interfaces("implements ")}输出所有接口, 'implements '开头,简写为 ${class.interfaces}
#foreach($field in ${class.fields})
   ${field.comment}
    ${field.type}
    ${field.name}
#end
  • ${class.fields} // 遍历输出所有类型
  • ${field.comment} // 属性注释,来自数据库的列注释
  • ${field.type} // 属性类型,例如 String、 Long等等
  • ${field.name} // 属性名,来自数据库列的名字(驼峰形式)
  • ${field.columnName} // 数据库列的原始名字
#call($class.imports.add(“io.swagger.annotations.ApiModel”))添加一个import引用类到文件头部
#call($class.snippets.add(“class_before”,“xxx”))定义一个代码片段,片段名字是 class_before
${class.snippets(‘class_before’)}输出名为 class_before 的 代码片段
2.4.2 velocity GenericTools
在模板中,你可以使用velocity GenericTools
官网参考: https://velocity.apache.org/tools/devel/generic.html
默认的配置读取自:io/github/kylinhunter/commons/template/velocity-tools.xml(k-commons.jar)

<tools>
  <toolbox scope="application">
    <tool class="org.apache.velocity.tools.generic.DateTool" format="yyyy-MM-dd"></tool>
    <tool class="org.apache.velocity.tools.generic.NumberTool"></tool>
    <tool class="org.apache.velocity.tools.generic.MathTool"></tool>
    <tool class="org.apache.velocity.tools.generic.DisplayTool"></tool>
    <tool class="org.apache.velocity.tools.generic.EscapeTool"></tool>
    <tool class="org.apache.velocity.tools.generic.FieldTool"></tool>
  </toolbox>
</tools>

示例:
${date}=>输出日期

2.4.3 自定义变量

在上面 k-generator-config.yaml 中,共有有三个位置去可以自定义变量,分别是

  1. modules.list[x].context
  2. templates.context
  3. templates.list[x].context

示例:
templates:
  context:
    'author': 'bijian'  # 定义一个名为 author 的变量
${author}=>输出变量author的值

3 示例

3.1 示例1 基础模板

3.1.1 定义模板 basic.vm(放到指定位置,参考上面的k-generator-config.yaml )
package ${class.packageName};
${class.imports("import ",";")}
 /**
  * @description  $!{class.comment}
  * @author ${author}
  * @since ${date}
  * ${basic_vm_custom_property}
  * ${module_custom_propery}
  **/
 public class ${class.name} ${class.superClass("extends ")} ${class.interfaces("implements ")}{
#foreach($field in ${class.fields})
 private ${field.type} ${field.name}; // ${field.comment}
#end
}
3.1.2 执行模板生成代码(代码输出位置参考上面的k-generator-config.yaml)
new io.github.kylinhunter.commons.generator.CodeGenerator().execute();
3.1.3 最终生成的源代码
package com.kylinhunter.user;
import java.util.ArrayList;
import java.io.Serializable;
import java.time.LocalTime;
import java.sql.Timestamp;
import java.sql.Date;
import java.sql.Time;
import java.math.BigDecimal;
/**
 * @description  the user
 * @author bijian
 * @since 2023-02-28
 * basic_vm_custom_property_value
 **/
public class UserBasic extends ArrayList implements Serializable,Cloneable{
    private Long id; // primary unique id
    private String name; // user name
    private LocalTime birth; // birthday
    private Timestamp leaveCompanyTime; // the time leave company
    private Date joinCompanyDate; // what time to join the company
    private Time workTimeWorkTime; // what time to work ervery moring
    private Integer workHours; // how many hours to work everyday
    private Short age; // age
    private Float height; // height
    private Double weight; // weight
    private BigDecimal moneyIncome; // all money income
    private Long moneySpend; // the money spent
    private String address; // address
    private Boolean deleteFlag; // is deleted
    private Integer sex; // 0 unkown 1 male 2 female
    private Integer roleId; // 角色 ID
}




3.2 示例2 (增加swagger功能支持)

3.2.1 定义模板 basic_swagger.vm (放到指定位置,参考上面的k-generator-config.yaml )
package ${class.packageName};
${class.imports("import ",";")}
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;

/**
 * @description  $!{class.comment}
 * @author ${author}
 * @since ${date}
 * ${basic_swagger_vm_custom_property}
 * ${module_custom_propery}
 **/
@ApiModel(value="${class.name}", description="$!{class.comment}")
public class ${class.name} ${class.superClass("extends ")} ${class.interfaces("implements ")}{
#foreach($field in ${class.fields})
@ApiModelProperty(value = "${field.comment}")
    private ${field.type} ${field.name};
#end
}



3.2.2 执行模板生成代码(代码输出位置参考上面的k-generator-config.yaml)
new io.github.kylinhunter.commons.generator.CodeGenerator().execute();
3.2.3 最终生成的源代码
package com.kylinhunter.user;
import java.util.ArrayList;
import java.io.Serializable;
import java.time.LocalTime;
import java.sql.Timestamp;
import java.sql.Date;
import java.sql.Time;
import java.math.BigDecimal;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;

/**
 * @description  the user
 * @author bijian
 * @since 2023-02-28
 * basic_swagger_vm_custom_property_value
 **/
@ApiModel(value="UserBasicSwagger", description="the user")
public class UserBasicSwagger extends ArrayList implements Serializable,Cloneable{
    @ApiModelProperty(value = "primary unique id")
    private Long id;
    @ApiModelProperty(value = "user name")
    private String name;
    @ApiModelProperty(value = "birthday")
    private LocalTime birth;
    @ApiModelProperty(value = "the time leave company")
    private Timestamp leaveCompanyTime;
    @ApiModelProperty(value = "what time to join the company")
    private Date joinCompanyDate;
    @ApiModelProperty(value = "what time to work ervery moring")
    private Time workTimeWorkTime;
    @ApiModelProperty(value = "how many hours to work everyday")
    private Integer workHours;
    @ApiModelProperty(value = "age")
    private Short age;
    @ApiModelProperty(value = "height")
    private Float height;
    @ApiModelProperty(value = "weight")
    private Double weight;
    @ApiModelProperty(value = "all money income")
    private BigDecimal moneyIncome;
    @ApiModelProperty(value = "the money spent")
    private Long moneySpend;
    @ApiModelProperty(value = "address")
    private String address;
    @ApiModelProperty(value = "is deleted")
    private Boolean deleteFlag;
    @ApiModelProperty(value = "0 unkown 1 male 2 female")
    private Integer sex;
    @ApiModelProperty(value = "角色 ID")
    private Integer roleId;
}



3.3 示例3 (增加swagger功能支持+利用 snippets 功能进行抽象)

3.3.1 利用 snippets 定义swagger代码片段 swagger.vm,形成一个抽象组件

假如模板在 /User/bijian/templates目录,则swagger.vm可以放到以下位置
/User/bijian/templates/commons/swagger.vm


#parse("io/github/kylinhunter/commons/generator/common.vm")
##添加开发包导入
#call($class.imports.add("io.swagger.annotations.ApiModel"))
#call($class.imports.add("io.swagger.annotations.ApiModelProperty"))
##定一个名为class_before 的代码片段
#set( $classAnnotation ='@ApiModel(value="'+${class.name}+'", description="'+$!{class.comment}+'")' )
#call($class.snippets.add("class_before",$classAnnotation))
#foreach($field in ${class.fields})
#set( $fieldAnnotation =  '@ApiModelProperty(value = "'+${field.comment}+'")')
##定义一个名为field_before 的代码片段
#call($field.snippets.add("field_before",$fieldAnnotation) )
#end


3.3.2 定义模板 basic_swagger_snippet.vm ,引用 上面的swagger.vm

#parse("commons/swagger.vm")
package ${class.packageName};
${class.imports("import ",";")}

/**
* @description  $!{class.comment}
* @author ${author}
* @since ${date}
* ${basic_swagger_snippet_vm_custom_property}
* ${module_custom_propery}
**/
${class.snippets('class_before')}
public class ${class.name} ${class.superClass("extends ")} ${class.interfaces("implements ")}{
#foreach($field in ${class.fields})
    ${field.snippets('field_before')}
    private ${field.type} ${field.name};
#end

}



3.3.4 执行模板生成代码(代码输出位置参考上面的k-generator-config.yaml)
new io.github.kylinhunter.commons.generator.CodeGenerator().execute();
3.1.4 最终生成的源代码
package com.kylinhunter.user;
import java.util.ArrayList;
import java.io.Serializable;
import java.time.LocalTime;
import java.sql.Timestamp;
import java.sql.Date;
import java.sql.Time;
import java.math.BigDecimal;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;

/**
 * @description  the user
 * @author bijian
 * @since 2023-02-28
 * basic_swagger_snippet_vm_custom_property_value
 **/
@ApiModel(value="UserBasicSwaggerSnippet", description="the user")
public class UserBasicSwaggerSnippet extends ArrayList implements Serializable,Cloneable{
    @ApiModelProperty(value = "primary unique id")
    private Long id;
    @ApiModelProperty(value = "user name")
    private String name;
    @ApiModelProperty(value = "birthday")
    private LocalTime birth;
    @ApiModelProperty(value = "the time leave company")
    private Timestamp leaveCompanyTime;
    @ApiModelProperty(value = "what time to join the company")
    private Date joinCompanyDate;
    @ApiModelProperty(value = "what time to work ervery moring")
    private Time workTimeWorkTime;
    @ApiModelProperty(value = "how many hours to work everyday")
    private Integer workHours;
    @ApiModelProperty(value = "age")
    private Short age;
    @ApiModelProperty(value = "height")
    private Float height;
    @ApiModelProperty(value = "weight")
    private Double weight;
    @ApiModelProperty(value = "all money income")
    private BigDecimal moneyIncome;
    @ApiModelProperty(value = "the money spent")
    private Long moneySpend;
    @ApiModelProperty(value = "address")
    private String address;
    @ApiModelProperty(value = "is deleted")
    private Boolean deleteFlag;
    @ApiModelProperty(value = "0 unkown 1 male 2 female")
    private Integer sex;
    @ApiModelProperty(value = "角色 ID")
    private Integer roleId;

}




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

羲圣

你的鼓励将是我创作的最大动力!

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值