Velocity (简称 VTL)是一个基于 Java 的模版引擎。它允许任何人仅仅使用简单的模板语言来引用由java代码定义的对象。
本案例使用 Velocity 动态生成 XML 文件
Velocity总体架构
APP模块
其中app主要封装了一些接口,暴露给使用者使用。主要有两个类,分别是Velocity(单例)和VelocityEngine
Velocity主要封装了一些静态接口,可以直接调用,帮助你渲染模板,只要传给Velocity一个模板和模板中对应的变量值就可以直接渲染
VelocityEngine类主要是供一些框架开发者调用的,它提供了更加复杂的接口供调用者选择,MVC框架中初始化一个VelocityEngine
Context模块
Context模块主要封装了模板渲染需要的变量,它的主要作用有两点:
- 便于与其他框架集成,起到一个适配器的作用,如MVC框架内部保存的变量往往在一个Map中,这样MVC框架就需要将这个Map适配到Velocity的context中
- Velocity内部做数据隔离,数据进入Velocity的内部的不同模块需要对数据做不同的处理,封装不同的数据接口有利于模块之间的解耦
Context类是外部框架需要向Velocity传输数据必须实现的接口,具体实现时可以集成抽象类AbstractContext,例如,Spring MVC中直接继承了VelocityContext,调用构造函数创建Velocity需要的数据结构
另外一个接口InternetEventContext主要是为扩展Velocity事件处理准备的数据接口,当你扩展了事件处理、需要操作数据时可以实现这个接口,并且处理你需要的数据
Runtime模块
整个Velocity的核心模块在runtime package下,这里会将加载的模板解析成JavaCC语法树,Velocity调用mergeTemplate方法时会渲染整棵树,并输出最终的渲染结果
RuntimeInstance类
RuntimeInstance类为整个Velocity渲染提供了一个单例模式,它也是Velocity的一个门面,封装了渲染模板需要的所有接口,拿到了这个实例就可以完成渲染过程了。它与VelocityEngine不同,VelocityEngine代表了整个Velocity引擎,它不仅包括模板渲染,还包括参数设置及数据的封装规则,RuntimeInstance仅仅代表一个模板的渲染状态
一、引入依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
<version>5.8.18</version>
</dependency>
<!-- Apache Velocity -->
<dependency>
<groupId>org.apache.velocity</groupId>
<artifactId>velocity-engine-core</artifactId>
<version>2.3</version>
</dependency>
二、模版文件
位置:resources\vm\demo.vm
## 测试
<?xml version="1.0" encoding="utf-8"?>
<TEST>
<Head>
<Time>$!{time}</Time>
</Head>
<Body>
<DEMO>
<ID>$!{id}</ID>
<STATUS/>
<LIST>
#foreach( $list in $listDemo )
<VALUE>$!{list.name}</VALUE>
#end
</LIST>
</DEMO>
</Body>
</TEST>
三、模版工具类
import cn.hutool.core.util.CharsetUtil;
import com.example.demo.velocity.domin.DemoTemplate;
import lombok.experimental.UtilityClass;
import org.apache.velocity.VelocityContext;
import org.apache.velocity.app.Velocity;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;
/**
* 模板工具类
*/
@UtilityClass
public class VelocityUtils {
/**
* 初始化 Velocity 环境
*/
public void initVelocity() {
Properties p = new Properties();
try {
// 加载classpath目录下的vm文件
p.setProperty("resource.loader.file.class",
"org.apache.velocity.runtime.resource.loader.ClasspathResourceLoader");
// 定义字符集
p.setProperty(Velocity.INPUT_ENCODING, CharsetUtil.UTF_8);
// 初始化Velocity引擎,指定配置Properties
Velocity.init(p);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
/**
* 设置批复模板变量信息
*
* @return 模板列表
*/
public VelocityContext prepareApprovalContext(DemoTemplate demoTemplate) {
VelocityContext velocityContext = new VelocityContext();
velocityContext.put("time", demoTemplate.getTime());
velocityContext.put("id", demoTemplate.getId());
velocityContext.put("listDemo", demoTemplate.getListDemo());
return velocityContext;
}
/**
* 获取模板信息
*
* @param tplCategory 模版类型
* @return 模板列表
*/
public List<String> getTemplateList(String tplCategory) {
List<String> templates = new ArrayList<String>();
if ("demo".equals(tplCategory)) {
templates.add("vm/demo.vm");
}
return templates;
}
/**
* 生成模板信息
*
* @param demoTemplate 模版数据
* @return 模板信息
*/
public static String getXmlByData(DemoTemplate demoTemplate) {
// 初始化上下文
VelocityUtils.initVelocity();
// 获取模版变量
VelocityContext context = VelocityUtils.prepareApprovalContext(demoTemplate);
if (Objects.isNull(context)) {
return StringUtils.EMPTY;
}
// 获取预制模版
List<String> templates = VelocityUtils.getTemplateList("demo");
StringWriter sw = new StringWriter();
for (String template : templates) {
// 渲染模板
Template tpl = Velocity.getTemplate(template, CharsetUtil.UTF_8);
tpl.merge(context, sw);
}
return sw.toString();
}
}
四、创建实体类
import lombok.Data;
import java.io.Serializable;
import java.util.List;
@Data
public class DemoTemplate implements Serializable {
private String id;
private String time;
private List<ListDemo> listDemo;
}
import lombok.Data;
import java.io.Serializable;
@Data
public class ListDemo implements Serializable {
private String name;
}
五、测试方法
import cn.hutool.core.collection.ListUtil;
import com.example.demo.velocity.VelocityUtils;
import com.example.demo.velocity.domin.DemoTemplate;
import com.example.demo.velocity.domin.ListDemo;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class VelocityController {
@GetMapping("velocityDemo")
public String velocityDemo(){
DemoTemplate demoTemplate = new DemoTemplate();
demoTemplate.setId("1");
demoTemplate.setTime("2023-08-01");
ListDemo listDemo = new ListDemo();
listDemo.setName("demo");
demoTemplate.setListDemo(ListUtil.of(listDemo));
return VelocityUtils.getXmlByData(demoTemplate);
}
}
相关链接:
介紹 | Velocity 中文文档https://wizardforcel.gitbooks.io/velocity-doc/content/
https://github.com/alibaba/velocity-spring-boot-projecthttps://github.com/alibaba/velocity-spring-boot-projecthttps://www.cnblogs.com/wade-luffy/p/5996848.htmlhttps://www.cnblogs.com/wade-luffy/p/5996848.html