代码生成器(二)代码生成器的开发

代码生成器开发(核心)

一、概述

  • 整体架构图

在这里插入图片描述

  • 思路
  1. 用户填写数据库信息,工程代建信息,把这些信息构造到实体类对象中
  2. 数据库表信息,数据库字段信息构造到实体类中
  3. 构造FreeMarker数据模型,把数据库表对象和基本配置存入到数据模型中
  4. 构造自定义公共代码模板
  5. 借助FreeMarker完成代码生成

二、搭建环境

1. 构造Maven工程,引入第三方依赖

  1. FreeMarker

  2. mysql驱动

2. 配置工具类

1)工具类的实现方式灵活且个性化十足,可以通过导入第三方工具类,也可以自己编写工具类

2)工具类清单:

  1. 字符串处理工具类
  2. 配置文件加载工具类
  3. 文件处理工具类
  4. 数据库处理工具类

3. 配置实体类

1)数据库配置

  1. JDBC配置实体类
  2. 数据表实体类
  3. 数据列实体类

2)工程配置

3)总结

这部分的任务就是把前台获取的配置信息封装到实体类中,方便后续加载数据表和构造数据模型

三、代码生成

1、流程

1)通过数据库处理工具类来获取数据库表实体对象

2)通过自定义配置数据表元数据生成工程配置构造数据模型

3)代码生成:a. 通过文件操作工具类扫描模板路径下的所有文件 b. 对每个模板使用数据模型进行插值

  1. 处理模板路径

    (1) 说明

    构造的模板文件名字可能存在不同,但都有很强的的规律性,一般都是类名+一般命名,故可以采用 FreeMarker的字符串模板插值的方式进行插值,最后把插值结果以流的形式在转换为字符串输出,赋值给生成模板文件作为文件名。

    (2)思路

    1、通过StringReader读取模板路径
    2、配合数据模型进行插值,把结果写入StringWriter
    3、把StringWriter转换为字符串

  2. 处理模板文件

    (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框架核心代码的自动生成。从此,面对数量庞大的数据表,不用再陷入无聊且易出错的代码复制粘贴困局。

猜你喜欢

转载自blog.csdn.net/weixin_38708854/article/details/106156465