系列文章:
Mavan:自定义骨架及工程初始化
一 前言
上一篇文章简单介绍了工程的初始化方法,本篇将探索代码生成技术。因为业务开发中使用 Java 语言较多,所以这里以 Java 作为背景语言。
大家熟知并且日常都在使用 Spring/SpringMVC/SpringBoot、Mybatis 框架,在开发中我们经常需要手写 Entity、Mapper、dao、service、controller 相关代码,这些重复性的工作会占用很多工作时间。如果有一个代码生成工具来做这些重复工作,显然可以提高我们的工作效率。这时,就需要了解模板引擎技术。
二 模板引擎工具:freemarker 与 velocity
最早接触的是 velocity,记得 14,15 年左右,当时在某家公司开发的前端页面,就是使用 velocity 作为模板引擎。创建前端页面的 vm/tpl 模板后,利用 velocity 提供的能力,编写脚本生成静态页面,然后再走上线更新。
除了 velocity 之外,freemarker 也是一款模板引擎,使用 FreeMarker Template Language(FTL)编写,它是一种简单的、专用的语言。
关于二者(有时也会包括 thymeleaf)的对比,已经有一些文章进行了分析,这里不再赘述,感兴趣的朋友可以搜索,或在评论中留言一起探讨。这里基于以前的一些调研工作,选择 freemarker 作为这里使用的模板引擎,用于示例。
三 freemarker 介绍
freemarker 的基础介绍,可以参考 freemarker 在线手册,中文版地址:http://freemarker.foofun.cn/。
简单来说,FreeMarker 是一款 模板引擎: 即一种基于模板和要改变的数据, 并用来生成输出文本(HTML 网页,电子邮件,配置文件,源代码等)的通用工具。 它不是面向最终用户的,而是一个 Java 类库,是一款程序员可以嵌入他们所开发产品的组件。
freemarker 的几个关键概念:模板(template)、Java 对象(Java Object)、输出(Output),三者含义和关系可通过下图体现:
(1)其中,template 是我们要使用的模板,基于这个模板来生成文件。简单来说,就是一些固定模式(代码/标签/逻辑)+变量的组合,其中变量在后面根据需要,替换成所需的值;
(2)Java Object 是模型/对象,可以简单理解为一些 key-value 对,key 是变量名称,value 就是变量的值;
(3)Output 是输出结果,在把 template 中的变量替换成 object 中的 value 后,就得到了我们预期的文件。
而替换的动作,就是由 freemarker 来实现的。
四 示例
4.1 工程结构
这里采用 maven 工程,idea 创建,工程目录结构如下:
4.2 依赖包引入-pom
<?xml version="1.0" encoding="UTF-8"?><project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion>
<groupId>org.example</groupId> <artifactId>template-engine</artifactId> <version>1.0-SNAPSHOT</version> <packaging>jar</packaging>
<dependencies> <dependency> <groupId>org.freemarker</groupId> <artifactId>freemarker</artifactId> <version>2.3.23</version> </dependency> </dependencies>
<build> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <version>2.0.2</version> <configuration> <source>1.8</source> <target>1.8</target> </configuration> </plugin> </plugins> <finalName>${project.artifactId}</finalName> </build></project>
复制代码
4.3 自定义 freemark 模板
这里预期是生成一个 Java 类,如下所示,是一个典型的 bean,包括几个属性和对应的 get/set 方法,几个变量: packageName-包名,className-类名,属性:id, userName, password
package ${packageName};
public class ${className} {
private Integer ${id};
private String ${userName};
private String ${password};
public Integer get${id?cap_first}(){ return ${id}; }
public void set${id?cap_first}(Integer ${id}){ this.${id}=${id}; }
public String get${userName?cap_first}(){ return ${userName}; }
public void set${userName?cap_first}(String ${userName}){ this.${userName}=${userName}; }
public String get${password?cap_first}(){ return ${password}; }
public void set${password?cap_first}(String ${password}){ this.${password}=${password}; }}
复制代码
4.4 定义生成代码方法
package com.freemark.demo.templates.util;
import freemarker.template.Configuration;import freemarker.template.Template;
import java.io.*;import java.util.HashMap;import java.util.Map;
public class FreemarkTest {
private static final String TEMPLATE_PATH = "src/main/java/com/freemark/demo/templates";
private static final String CLASS_PATH = "src/main/java/com/freemark/demo";
public static void main(String[] args) { // 创建freeMarker配置实例 Configuration configuration = new Configuration(); Writer out = null; try {
// 设置模版路径 configuration.setDirectoryForTemplateLoading(new File(TEMPLATE_PATH)); // 创建数据模型 Map<String, Object> dataMap = new HashMap<>(); dataMap.put("packageName", "com.freemark.demo"); dataMap.put("className", "Test"); dataMap.put("id", "id"); dataMap.put("userName", "userName"); dataMap.put("password","password");
// 加载模版文件 Template template = configuration.getTemplate("test.ftl");
// 生成文件流 File docFile = new File(CLASS_PATH + "/" + "Test.java"); out = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(docFile)));
// 输出到文件 template.process(dataMap, out); System.out.println("Test.java 源码生成成功!"); } catch (Exception e) { e.printStackTrace(); } finally { try { if (null != out) { out.flush(); } } catch (Exception e2) { e2.printStackTrace(); } } }}
复制代码
我们运行 main 方法,可以看到控制台会打印出 Test.java 源码生成成功! 并在 src/main 指定的包下,生成了 Test.java 类文件,内容如下:
package com.freemark.demo;
public class Test {
private Integer id;
private String userName;
private String password;
public Integer getId(){ return id; }
public void setId(Integer id){ this.id=id; }
public String getUserName(){ return userName; }
public void setUserName(String userName){ this.userName=userName; }
public String getPassword(){ return password; }
public void setPassword(String password){ this.password=password; }}
复制代码
评论