一种基于数据库与渲染模板的代码生成器——模板渲染

网友投稿 749 2022-05-30

续上篇

在前两篇文章《一种基于数据库+模板渲染的代码生成器——简介及数据库查询》以及《一种基于数据库+模板渲染的代码生成器——表结构暂存与类设计》中,我们介绍了如何通过mysql中的自有数据库information_schema查询数据库结构,以及通过另外构建数据表gen_table与gen_table_column,暂存数据结构,暂存表所生成的类名,属性等等,减少后续生成代码预览与频繁生成的数据库压力与代码复杂度。

本篇我们继续阐述代码生成器的后续逻辑——模板渲染。

几种Java中常见的模板渲染插件

字符串格式化工具

最简单的,我们知道Java自带的格式化输出:

System.out.printf("%f\n",pi);

一种基于数据库与渲染模板的代码生成器——模板渲染

一些常用的工具中也有一些非常好用的模板化字符串的方法。

以著名的开源库Hutool为例,其中的StrUtil中的函数用法如下:

String template = "{}爱{},就像老鼠爱大米"; String str = StrUtil.format(template, "我", "你"); //str -> 我爱你,就像老鼠爱大米

freemaker

这是笔者最常用的一个渲染引擎,功能非常强大,一方面可以使用它来渲染网页,邮件等显示页面,另一方面,也可以用它通过配置复杂的XML文档,导出为word等格式;当然,也可以使用其生成想要的源代码。

freemaker中的渲染使用示意图如下:

上图是Freemaker官网上的一张示意图,在模板中设置${name}字段,在Java中通过对象或Map,设置其name值,通过freemaker即可生成指定文件。其模板文件大多格式为.ftl。

一个简单的使用代码如下:

/**忽略try-catch等语句*/ Map dataMap = new HashMap<>(); dataMap.put("name", "姓名"); configuration = new Configuration(); configuration.setDefaultEncoding("utf-8"); configuration.setClassForTemplateLoading(com.backstage.export.template.Template.class, "/模板存储路径"); Template t = configuration.getTemplate("模板文件.ftl"); // 输出文档路径及名称 File outFile = new File(fileName); Writer out = null; FileOutputStream fos = null; fos = new FileOutputStream(outFile); OutputStreamWriter oWriter = new OutputStreamWriter(fos, "UTF-8"); out = new BufferedWriter(oWriter); t.process(dataMap, out); out.close(); fos.close();

Apache Velocity

与Freemaker相似,使用上相比Freemaker来说,稍微复杂一些。

// 初始化:设置模板主路径,字符集,指定配置等 VelocityInitializer.initVelocity(); // context类似与freemaker中的map等数据对象,存储数据{"name": "落叶"} VelocityContext context = VelocityUtils.prepareContext(data); // 获取模板 Template tpl = Velocity.getTemplate("/模板路径/模板.file-suffix.vm", Constants.UTF8); // 渲染 StringWriter sw = new StringWriter(); tpl.merge(context, sw); System.out.println(sw.toString());

在我们学习的若依系统中,其使用的是Apache Velocity。

首先,查询gen_table表,将指定表的结构信息查询出来:

// 查询表信息: GenTable table = genTableMapper.selectGenTableById(tableId);

需要注意的是,上述查询,不仅查出来gen_table表,也包括gen_table_column表的数据,这源于GenTable对象设计为:

public class GenTable extends BaseEntity { // ... /** 表列信息 */ @Valid private List columns; // ... }

然后准备模板渲染对象VelocityContext:

/** * 设置模板变量信息 * * @return 模板列表 */ public static VelocityContext prepareContext(GenTable genTable) { VelocityContext velocityContext = new VelocityContext(); velocityContext.put("tplCategory", genTable.getTplCategory()); velocityContext.put("tableName", genTable.getTableName()); velocityContext.put("functionName", StringUtils.isNotEmpty(functionName) ? functionName : "【请填写功能名称】"); velocityContext.put("ClassName", genTable.getClassName()); velocityContext.put("className", StringUtils.uncapitalize(genTable.getClassName())); velocityContext.put("moduleName", genTable.getModuleName()); // ..... velocityContext.put("columns", genTable.getColumns()); return velocityContext; }

代码生成器的模板还是十分复杂的,我们选其中一个Domain的模板来看其中的一部分:

package ${packageName}.domain; #foreach ($import in $importList) import ${import}; #end import org.apache.commons.lang3.builder.ToStringBuilder; import org.apache.commons.lang3.builder.ToStringStyle; import com.ruoyi.common.annotation.Excel; #if($table.crud || $table.sub) import com.ruoyi.common.core.domain.BaseEntity; #elseif($table.tree) import com.ruoyi.common.core.domain.TreeEntity; #end /** * ${functionName}对象 ${tableName} * * @author ${author} * @date ${datetime} */ #if($table.crud || $table.sub) #set($Entity="BaseEntity") #elseif($table.tree) #set($Entity="TreeEntity") #end public class ${ClassName} extends ${Entity} { private static final long serialVersionUID = 1L; #foreach ($column in $columns) #if(!$table.isSuperColumn($column.javaField)) /** $column.columnComment */ #if($column.list) #set($parentheseIndex=$column.columnComment.indexOf("(")) #if($parentheseIndex != -1) #set($comment=$column.columnComment.substring(0, $parentheseIndex)) #else #set($comment=$column.columnComment) #end #if($parentheseIndex != -1) @Excel(name = "${comment}", readConverterExp = "$column.readConverterExp()") #elseif($column.javaType == 'Date') @JsonFormat(pattern = "yyyy-MM-dd") @Excel(name = "${comment}", width = 30, dateFormat = "yyyy-MM-dd") #else @Excel(name = "${comment}") #end #end private $column.javaType $column.javaField; #end #end }

输出:

// 渲染模板 StringWriter sw = new StringWriter(); Template tpl = Velocity.getTemplate(template, Constants.UTF8); tpl.merge(context, sw); dataMap.put(template, sw.toString());

总结

至此,我们就大概了解了一个代码生成器是如何将表结构列信息等一步一步转换为可以使用的源代码的过程。

数据库 渲染

版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:Java SAX解析XML
下一篇:一小时内在本地搭建 SAP Commerce Cloud(电商云)的前后台运行环境
相关文章