系列文章:
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
代码语言:javascript复制<?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
代码语言:javascript复制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 定义生成代码方法
代码语言:javascript复制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类文件,内容如下:
代码语言:javascript复制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;
}
}