系列文章:
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;
}
}
复制代码
评论