代码生成器开发(核心)
一、概述
- 整体架构图
- 思路
- 用户填写数据库信息,工程代建信息,把这些信息构造到实体类对象中
- 数据库表信息,数据库字段信息构造到实体类中
- 构造FreeMarker数据模型,把数据库表对象和基本配置存入到数据模型中
- 构造自定义公共代码模板
- 借助FreeMarker完成代码生成
二、搭建环境
1. 构造Maven工程,引入第三方依赖
2. 配置工具类
1)工具类的实现方式灵活且个性化十足,可以通过导入第三方工具类,也可以自己编写工具类
2)工具类清单:
- 字符串处理工具类
- 配置文件加载工具类
- 文件处理工具类
- 数据库处理工具类
3. 配置实体类
1)数据库配置
2)工程配置
3)总结
这部分的任务就是把前台获取的配置信息封装到实体类中,方便后续加载数据表和构造数据模型
三、代码生成
1、流程
1)通过数据库处理工具类
来获取数据库表实体对象
2)通过自定义配置
、数据表元数据
、生成工程配置
构造数据模型
3)代码生成:a. 通过文件操作工具类
扫描模板路径下的所有文件 b. 对每个模板使用数据模型
进行插值
-
处理模板路径
(1) 说明
构造的模板文件名字可能存在不同,但都有很强的的规律性,一般都是
类名+一般命名
,故可以采用 FreeMarker的字符串模板插值
的方式进行插值,最后把插值结果以流的形式在转换为字符串输出,赋值给生成模板文件作为文件名。(2)思路
1、通过
StringReader
读取模板路径
2、配合数据模型
进行插值,把结果写入StringWriter
3、把StringWriter
转换为字符串 -
处理模板文件
(1)思路
1、通过FreeMarker配置器获取模板文件
2、设定模板输出为utf-8
编码方式
3、通过文件工具类提前生成模板文件所在父目录
4、配合数据模型
生成模板文件
5、关闭文件写入流
四、核心代码
1、调用代码生成器的入口
//UI调用程序入口
/**
*
* @param templetPath 模板所在路径
* @param outpath 选择代码生成路径
* @param settings 工程配置对象
* @param db 数据库信息
*/
private void generator(String templetPath,String outpath,Settings settings,DataBase db) throws Exception {
GeneratorFacade gf = new GeneratorFacade(templetPath,outpath,settings,db);
gf.generatorByDataBase();
}
2、代码生成器数据模型整合类(核心)
/**
* 代码生成器的核心入口类
*/
public class GeneratorFacade {
private String templatePath;
private String outPath;
private Settings settings;
private DataBase db;
private Generator generator;
public GeneratorFacade(String templatePath, String outPath, Settings settings, DataBase db) throws Exception {
this.templatePath = templatePath;
this.outPath = outPath;
this.settings = settings;
this.db = db;
this.generator = new Generator(templatePath,outPath);
}
/**
* 1.准备数据模型
* 2.调用核心处理类完成代码生成工作
*/
public void generatorByDataBase() throws Exception {
List<Table> tables = DataBaseUtils.getDbInfo(db);
for (Table table : tables) {
Map<String,Object> dataModel = getDataModel(table);
generator.scanAndGenerator(dataModel);
}
}
/**
* 根据table对象获取数据模型
*/
private Map<String,Object> getDataModel(Table table){
Map<String,Object> dataModel = new HashMap<>();
// 1.自定义配置
dataModel.putAll(PropertiesUtils.customMap);
// 2.元数据
dataModel.put("table",table);
// 3.setting
dataModel.putAll(this.settings.getSettingMap());
// 4.类型
dataModel.put("ClassName",table.getName2());
return dataModel;
}
}
3、代码生成类(核心)
/**
* 代码生成器的核心处理类
*/
public class Generator {
private String templatePath; //模板路径
private String outPath; //代码生成路径
private Configuration cfg;
public Generator(String templatePath, String outPath) throws Exception {
this.templatePath = templatePath;
this.outPath = outPath;
//实例化Configuration
cfg = new Configuration();
// 指定模板加载器
FileTemplateLoader fil = new FileTemplateLoader(new File(templatePath));
cfg.setTemplateLoader(fil);
}
/**
* 代码生成
* 1. 扫描模板路径下的所有模板
* 2. 对每个模板进行代码填充生成(数据模型)
*/
public void scanAndGenerator(Map<String,Object> dataModel) throws Exception {
//1. 根据模板路径找到此路径下的所有模板文件
List<File> fileList = FileUtils.searchAllFile(new File(templatePath));// 提供一个相对路径
//2. 每个模板文件生成
for (File file: fileList){
executeGenertor(dataModel,file);
}
}
/**
* 对模板进行文件生成
* @param dataModel
* @param file
* 模板文件:c: com.example.abc.java
*/
private void executeGenertor(Map<String,Object> dataModel, File file) throws Exception {
//1. 文件路径的处理 (E:\模板\${path1}\${path2}\${path3}\${ClassName}.java})
System.out.println("file = " + file);
String templateFileName = file.getAbsolutePath().replace(this.templatePath,""); // 得到绝对路径
System.out.println("absoultePathFile = " + templateFileName);
String outFileName = processTemplateString(templateFileName,dataModel);
//2. 读取文件模板
Template template = cfg.getTemplate(templateFileName);
template.setOutputEncoding("utf-8");
//3. 创建输出的模板文件
File file1 = FileUtils.mkdir(outPath,outFileName);
//4. 模板处理(文件生成)
FileWriter fw = new FileWriter(file1);
template.process(dataModel,fw);
fw.close();
}
public String processTemplateString(String templateString, Map dataModel) throws Exception {
StringWriter out = new StringWriter();
Template template = new Template("name1",new StringReader(templateString),cfg);
System.out.println("templateString = " + templateString + ", dataModel = " + dataModel);
template.process(dataModel,out);
System.out.println(out.toString());
return out.toString();
}
}
五、总结
以上便是代码生成的核心代码,通过以上代码可以实现一个简单的SpringBoot框架核心代码的自动生成。从此,面对数量庞大的数据表,不用再陷入无聊且易出错的代码复制粘贴困局。