遇到重复工作一定想办法将其转化为自动化,我觉得这才是合格的程序猿。我们日常开发中遇到的80%的代码都是增删改查,当然,已经有一些插件,比如MP提供了一整套的代码生成方案,但是提供的基本都是java代码,因为模板语言有太多种,根据每个人每个项目的不同而不同,但是,模板中一样也基本是列表和表单提交,怎么来解决这个重复工作呢?
思路:依然依赖mp组件,因为mp已经提供了对应的BaseService,BaseMapper等,但是本文重点不在于“怎么用”,而在于“怎么写”。“怎么写”属于自己的代码生成器,方便自己随意扩展前端页面生成。
前提-数据库设计约定:表名、字段名多个单词时下划线分割
读取数据库,解析各个表字段及备注
实体类生成:根据字段名解析为对应实体类属性名,同时注释为属性注释
定义生成模板(xxx.ftl)
前端页面:数据库字段备注为表单中的字段名,根据字段类型设置输入项的html标签
分别生成实体类、Mapper、Service、前端页面等
替换(xxx.ftl)中的变量
一、TableInfo对象
一、JDBC读取数据库表结构
publicMapgetTables(){
try{
DatabaseMetaDatadatabaseMetaData=getConn().getMetaData();
ResultSetresultSet=databaseMetaData.getColumns(null,"%","%","%");
MaptableInfoMap=newHashMap<>(8);
while(resultSet.next()){
StringtableName=resultSet.getString("TABLE_NAME");
TableInfotableInfo=tableInfoMap.get(tableName);
if(tableInfo==null){
tableInfo=newTableInfo(tableName,StringUtil.toHump(tableName,true));
}
StringcolName=resultSet.getString("COLUMN_NAME");
Stringremark=resultSet.getString("REMARKS");
StringcolType=resultSet.getString("TYPE_NAME");
ListcolInfos=tableInfo.getColInfos();
if(colInfos==null||colInfos.size()==0){
colInfos=newArrayList<>();
}
ColInfocolInfo=newColInfo(colName,colType,remark);
colInfos.add(colInfo);
tableInfo.setColInfos(colInfos);
tableInfoMap.put(tableName,tableInfo);
}
returntableInfoMap;
}catch(SQLExceptione){
e.printStackTrace();
}
returnnull;
}
二、生成实体类
dataMap 存放渲染ftl模板时的数据。
publicvoidgenerateModel(StringdiskPath,TableInfotableInfo){
StringtemplateName="model.ftl";
Stringpath=diskPath+File.separator+tableInfo.getModelName()+TableInfo.GEN_SUFFIX;
MapdataMap=newHashMap<>();
dataMap.put("ModelName",tableInfo.getModelName());
dataMap.put("packageName","com.mos.aaa");
ListcolInfos=tableInfo.getColInfos();
dataMap.put("fields",colInfos);
Listpcks=newArrayList<>();
for(ColInfoinfo:colInfos){
if(StringUtil.isNotBlank(info.getFieldType().getPkg())&&!pcks.contains(info.getFieldType().getPkg())){
pcks.add(info.getFieldType().getPkg());
}
}
dataMap.put("pcks",pcks);
generateFileByTemplate(templateName,path,dataMap);
}
三、Model模板定义(用来生成Entity)
package${packageName};
importcom.baomidou.mybatisplus.activerecord.Model;
importjava.io.Serializable;
import${pck!};
#list>
#if>
publicclass${ModelName}extendsModel{
privatestaticfinallongserialVersionUID=1L;
/**
* ${field.remark!}
*/
private${field.fieldType.type}${field.changedColNameLower};
#list>
public${field.fieldType.type}get${field.changedColName}(){
return${field.changedColNameLower};
}
publicvoidset${field.changedColName}(${field.fieldType.type}${field.changedColNameLower}){
this.${field.changedColNameLower}=${field.changedColNameLower};
}
#list>
@Override
protectedSerializablepkVal(){
returnthis.id;
}
}
四、最终文件生成
privatevoidgenerateFileByTemplate(finalStringtemplateName,StringgenPath,MapdataMap){
try{
Templatetemplate=FreeMarkerTemplateUtils.getTemplate(templateName);
FileOutputStreamfos=newFileOutputStream(newFile(genPath));
Writerout=newBufferedWriter(newOutputStreamWriter(fos,"utf-8"),10240);
template.process(dataMap,out);
}catch(Exceptione){
System.out.println(e.getMessage());
}
}
五、生成结果
六、扩展
以上只是生成简单的Entity实体类示例。一般我们后台页面结构为左、上、下、中四部分,我们只需要生成“中”部分即可,可以根据一个已完成的页面,替换其中的变量即可,生成原理同上。如有需要,可以关注我的公众号【陌与尘埃】或者关注我的开源项目【EBOOT】,后面我会将完整的代码生成器开源出来,欢迎大家一起来完善~~~