前言风油精的电y电妙用(1):在电风扇的叶子上洒上几滴风油精,随着风叶的脑配脑配不停转动,可使满室清香,置生置生而且有驱赶蚊子的成器成器效用。不知各位看官在工作之中有没有陷入过疯狂CV代码、京东看着密密麻
前言
风油精的电y电超长续航智能手机 非常好妙用(1):在电风扇的叶子上洒上几滴风油精,随着风叶的脑配脑配不停转动,可使满室清香,置生置生而且有驱赶蚊子的成器成器效用。
不知各位看官在工作之中有没有陷入过疯狂CV代码、京东看着密密麻麻的电y电类不想动手,或者把大把的脑配脑配时间花费在底层的情况。以笔者为例,置生置生会经常遇到以下两个问题:
- 隔一段时间就需要构建一个新应用,成器成器需要各种复制粘贴(缺乏定制化的京东脚手架)
- 新需求一堆的Entity、Bean、Request、Response、DTO、Dao、杭州丝绸 极出彩Service、Business需要写,看着都不想动手
很多时候甚至会在复制粘贴代码时漏掉一些关键的注解,比如:@Service,导致项目无法启动,再花费更多的精力去排查。因此本文将以实际工程代码为例,来构建一个可定制化,支持高度扩展的代码生成器。
项目目标
本项目将基于生成器项目生成一个可直接运行/可方便一键复制的SpringBoot成品项目,其中包括基本的数据库操作、业务操作及Web接口、视图层。
同时支持拔插式自定义实现,具备较高的拓展性,以下是项目基本结构:
Code-Generate├── pom.xml├── src│ ├── main│ │ ├── java│ │ │ └── com│ │ │ └── mysql│ │ │ ├── App.java// 程序入口│ │ │ ├── bean│ │ │ │ ├── ClassInfo.java// 类实体(对应表维度)│ │ │ │ ├── ConfigurationInfo.java// 配置中心│ │ │ │ ├── FieldInfo.java// 字段实体(对应表字段维度)│ │ │ │ └── GlobleConfig.java// 全局配置│ │ │ ├── engine│ │ │ │ ├── AbstractEngine.java// 抽象引擎│ │ │ │ ├── GeneralEngine.java// 接口引擎│ │ │ │ └──impl│ │ │ │ ├── CustomEngineImpl.java// 自定义引擎(拔插式基类)│ │ │ │ └── DefaultEngine.java// 默认引擎│ │ │ ├── factory│ │ │ │ ├── ClassInfoFactory.java// 类工厂(非必要,可融进上述配置中心)│ │ │ │ └── PropertiesFactory.java// 配置文件工厂(非必要,可融进上述配置中心)│ │ │ ├── intercept│ │ │ │ ├── CustomEngine.java│ │ │ │ └──impl│ │ │ │ ├── DataMdImpl.java// 自定义引擎案例一(数据库文档)│ │ │ │ └── LayUiHtmlImpl.java// 自定义引擎案例二(视图界面)│ │ │ └── util│ │ │ ├── DataBaseUtil.java// 数据库依靠│ │ │ ├── DBUtil.java// 数据库操作类│ │ │ ├── IOTools.java// 工具类│ │ │ └── StringUtil.java// 工具类│ │ ├── resources│ │ │ ├── application.properties// 配置文件│ │ │ ├── log4j2.xml// 日志配置│ │ │ └── templates// 模板目录│ │ └── test│ └── META-INF └── MANIFEST.MF// META-INF文件,为了打成Jar包使用(非必须)复制代码
编码
构建配置中心
由于本项目涉及数据库操作层等,杭州丝绸 特超群因此除了目标目录,项目名,作者,根目录等基本参数外,还需要数据库相关配置等,配置文件如下:
数据库IP, 数据库Driver, 编码, 用户名, 密码ip=127.0.0.1port=3306driver=com.mysql.jdbc.DriverdataBase=school-miaoencoding=UTF-8loginName=rootpassWord=需要构建的表名 为* 默认包含全部, 以;号隔离比如: a;b;c;d;include=*;项目名projectName=Demo包名packageName=com.demo作者authorName=Kerwin项目输出根目录rootPath=F:\\code自定义Handle包含项, 现有自定义模块:DataMdImpl,LayUiHtmlImpl, * 号默认包含所有,以;号隔离比如: a;b;c;d;customHandleInclude=DataMdImpl;LayUiHtmlImpl;复制代码
考虑好基础的配置内容后,通过读取文件配置,将相关信息置入配置中心即可,具体代码便不再展示,需要的直接观看源码即可(文末链接)。
本阶段涉及的类:ConfigurationInfo.java、GlobleConfig.java、PropertiesFactory。
入口:com.mysql.engine.AbstractEngineinit
基于数据库获取表字段信息
上文已获取到目标数据库的配置信息,本阶段即可连接数据库,通过通用SQL获取目标库的表、字段信息。
以下面的SQL为例,只需获取数据库连接加上库信息,即可获取所有的表名
SELECTtable_nameFROMinformation_schema.TABLESWHEREtable_schema ="school-miao-demo"库名ANDtable_type ="base table";响应schools复制代码
同理,通过通用SQL也可以获取到指定数据表的所有字段及其类型:
SELECTcolumn_name, data_type, column_comment, numeric_precision, numeric_scale, character_maximum_length, is_nullable nullableFROMinformation_schema.COLUMNSWHEREtable_name =schools表明ANDtable_schema =school-miao-demo;库名结果为column_name data_typesname varchar复制代码
得到表字段的类型后存储至配置中心即可,其中的关键一点在于需要注意数据类型的映射,比如varchar映射String,int映射Integer等等,同时把表字段通过字符串处理工具类转化为驼峰类型(固定类型)的展示方式,例如:s_id => sid,这一点上需要注意数据库字段的设计规范。
基于模板生成文件
本项目中最关键的一点即在于此,如果想要实现可配置化代码生成器,一定有一个前提即:配置本身,回忆我们在多年前初学JSP的时候,有没有觉得JSTL表达式还蛮神奇的,它可以将Java语言和HTML语言完美的混合在一起,虽然现在我们已不再使用它,但是这种模板化的思想和工作方式,恰好可以用在此处。
通过调研发现,在类似JSP的技术中,FreeMarker完美符合我们的预期,其中它的:
freemarker.template.Templateprocess(java.lang.Object, java.io.Writer)
方法,可以通过指定模板文件(FTL)、Java实体、目标文件的方式,来帮助我们实现内容的填充,使用方法类似JSTL,如下:
package ${ packageName}.entity;importjava.io.Serializable;importlombok.Data;importjava.util.Date;importjava.util.List;/** * ${ classInfo.classComment} * @author ${ authorName} ${ .now?string(yyyy-MM-dd)} */@Datapublicclass${ classInfo.className} implementsSerializable{ privatestaticfinallong serialVersionUID = 1L;