🔥码云GVP开源项目 12k star Uniapp+ElementUI 功能强大 支持多语言、二开方便! 广告
## 一、代码生成器的基础实现原理 相信大部分的开发者都使用过或者听说过“模板引擎”,它可以帮我们实现视图与数据的分离,快速开发视图页面,并将模板整合结果用于在浏览器显示。其核心实现原理就是:HTML模板页面 + 页面数据 = 输出结果。页面视图输出的过程就是通过模板引擎实现的。 ![](https://img.kancloud.cn/7d/f8/7df8fd753d1a81771a0b1ebd55eca892_815x355.png) 代码生成器的实现原理与模板引擎实现页面渲染的逻辑几乎是一致的,除了下面的几个区别: * 所谓模板:就是某语言的代码 + 模板引擎语法的占位符,该占位符用来数据天换。所以代码生成器的模板文件不再专指HTML页面模板文件,可以是任何类型的代码文件。 * 模板引擎的输出结果在项目中是输出给浏览器进行页面渲染的,但是对于代码生成器而言,模板引擎的输出结果是保存到磁盘文件。 ![](https://img.kancloud.cn/5a/b1/5ab15fa3f2bd3537b4bb1a625cac6949_912x396.png) ## 二、如何编写模板文件 要编写模板文件,首先我们要知道正常的代码待如何书写。比如下面的POJO代码: ![](https://img.kancloud.cn/18/cf/18cf3aabf8b703b7af1f186a15b86df4_949x634.png) 上面的POJO代码写成Freemarker模板文件,就是下面的样子: ~~~ package ${package.Entity}; <#list table.importPackages as pkg> import ${pkg}; </#list> <#if entityLombokModel> import lombok.Data; import lombok.EqualsAndHashCode; </#if> /** * <p> * ${table.comment!} * </p> * * @author ${author} * @since ${date} */ <#if entityLombokModel> @Data <#if superEntityClass??> @EqualsAndHashCode(callSuper = true) <#else> @EqualsAndHashCode(callSuper = false) </#if> </#if> public class ${entity} extends Model<${entity}> { <#list table.fields as field> private ${field.propertyType} ${field.propertyName}; </#list> ~~~ Mybatis Plus 代码生成的模板文件:[https://gitee.com/baomidou/mybatis-plus/tree/3.0/mybatis-plus-generator/src/main/resources/templates](https://gitee.com/baomidou/mybatis-plus/tree/3.0/mybatis-plus-generator/src/main/resources/templates) ## 三、数据从哪里来? 有了模板文件,我们想通过模板引擎生成代码,下面的一个问题就是数据从哪里来?有了数据我们才能生成代码 * 从配置中来,比如:package路径等一些静态化不经常变化的信息,一个项目生成的代码存放的包路径通常不会经常变化。 * 从数据库中来,比如:实体类名称、实体类字段名称、实体类字段类型等信息。类似于逆向工程,通过数据库表名、字段名、字段类型等信息生成实体信息。 ### 3.1.以MySQL的INFORMATION\_SCHEMA信息获取为例 我们的代码自动生成是针对数据库操作,所以首先要了解数据库表的结构 ~~~ SELECT column_name,data_type,is_nullable,character_maximum_length,column_comment FROM INFORMATION_SCHEMA.COLUMNS WHERE table_name='kpi_task' AND table_schema='home' ORDER BY ordinal_position ~~~ 如上图SQL查询的是home库,kpi\_task表的信息,如下: ![](https://img.kancloud.cn/66/18/661852ed844a57e1c6e0a11e72431683_761x396.png) * column\_name作为表的字段可以生成实体类的成员变量参数名称(通常是驼峰标识规则) * data\_type,is\_nullable,character\_maximum\_length可用于生成校验规则。 * 注释可以用于生成column\_comment ## 四、Mybatis Plus代码生成器的使用 如果上面的代码生成器实现原理你都看懂了,下面的这些配置你也就不难理解了。 ### 4.1.添加依赖 * 添加 代码生成器 依赖 ~~~ <dependency> <groupId>com.baomidou</groupId> <artifactId>mybatis-plus-generator</artifactId> <version>3.3.2</version> </dependency> ~~~ * 添加 模板引擎 依赖,MyBatis-Plus 支持 Velocity(默认)、Freemarker、Beetl,用户可以选择自己熟悉的模板引擎。 Velocity(默认): ~~~ <dependency> <groupId>org.apache.velocity</groupId> <artifactId>velocity-engine-core</artifactId> <version>2.2</version> </dependency> ~~~ Freemarker: ~~~ <dependency> <groupId>org.freemarker</groupId> <artifactId>freemarker</artifactId> <version>2.3.30</version> </dependency> ~~~ Beetl: ~~~ <dependency> <groupId>com.ibeetl</groupId> <artifactId>beetl</artifactId> <version>3.1.8.RELEASE</version> </dependency> ~~~ 注意!如果您选择了非默认引擎,需要在 AutoGenerator 中 设置模板引擎。 ~~~ AutoGenerator generator = new AutoGenerator(); // set freemarker engine generator.setTemplateEngine(new FreemarkerTemplateEngine()); // set beetl engine generator.setTemplateEngine(new BeetlTemplateEngine()); // set custom engine (reference class is your custom engine class) generator.setTemplateEngine(new CustomTemplateEngine()); // other config ... ~~~ ### 4.2.代码生成配置 AutoGenerator 是 MyBatis-Plus 的代码生成器,通过 AutoGenerator 可以快速生成 Entity、Mapper、Mapper XML、Service、Controller 等各个模块的代码,极大的提升了开发效率。 执行下面的这个测试用例,Mybatis Plus就可以帮助我们实现以上各层的代码生成到对应的package路径下面 ~~~ public class CodeGenerator { @Test public void startGenerator() { //1、全局配置 GlobalConfig config = new GlobalConfig(); String projectPath = System.getProperty("user.dir"); config.setActiveRecord(true)//开启AR模式 .setAuthor("zimug")//设置作者 .setOutputDir(projectPath + "/src/main/java")//生成路径(一般在此项目的src/main/java下) .setFileOverride(true)//第二次生成会把第一次生成的覆盖掉 .setOpen(true)//生成完毕后是否自动打开输出目录 //.setSwagger2(true)//实体属性 Swagger2 注解 //.setIdType(IdType.AUTO)//主键策略 .setServiceName("%sService")//生成的service接口名字首字母是否为I,这样设置就没有I .setBaseResultMap(true)//生成resultMap .setBaseColumnList(true);//在xml中生成基础列 //2、数据源配置 DataSourceConfig dataSourceConfig = new DataSourceConfig(); dataSourceConfig.setDbType(DbType.MYSQL)//数据库类型 .setDriverName("com.mysql.jdbc.Driver") .setUrl("jdbc:mysql://localhost:3306/zimug") .setUsername("root") .setPassword("zimug3456"); //3、策略配置 StrategyConfig strategyConfig = new StrategyConfig(); strategyConfig.setCapitalMode(true)//开启全局大写命名 .setNaming(NamingStrategy.underline_to_camel)//表名映射到实体的命名策略(下划线到驼峰) //表字段映射属性名策略(未指定按naming) .setColumnNaming(NamingStrategy.underline_to_camel) //.setTablePrefix("tb_")//表名前缀 //.setSuperEntityClass("你自己的父类实体,没有就不用设置!") //.setSuperEntityColumns("id");//写于父类中的公共字段 //.setSuperControllerClass("自定义继承的Controller类全称,带包名,没有就不用设置!") .setRestControllerStyle(true) //生成 @RestController 控制器 .setEntityLombokModel(true)//使用lombok .setInclude("sys_user","sys_role");//逆向工程使用的表 //4、包名策略配置 PackageConfig packageConfig = new PackageConfig(); packageConfig.setParent("com.zimug.example")//设置包名的parent .setMapper("mapper") .setService("service") .setController("controller") .setEntity("entity") .setXml("mapper");//设置xml文件的目录 //5、整合配置 AutoGenerator autoGenerator = new AutoGenerator(); autoGenerator.setGlobalConfig(config) .setDataSource(dataSourceConfig) .setStrategy(strategyConfig) .setPackageInfo(packageConfig); //6、执行 autoGenerator.execute(); } } ~~~ 参考:[https://blog.csdn.net/j3T9Z7H/article/details/107455087](https://blog.csdn.net/j3T9Z7H/article/details/107455087)