什么是velocity
velocity是一个基于java的模板引擎,可以通过特定的语法获取在java对象的数据,填充到模板中,从而实现界面和Java的分离。
应用场景
Web应用场景:作为应用程序的试图,展示数据。
源代码生成:velocity可以用来基于模板生成java源代码
自动电子邮箱:网站注册,认证等的电子邮箱模板
网页静态化:基于velocity模板生成静态网页
快速入门demo
使用velocity定义一个html模板,将动态数据填充到模板中形成一个完整的HTML页面
1.创建项目
2.引入依赖
<!--velocity模板引擎-->
<dependency>
<groupId>org.apache.velocity</groupId>
<artifactId>velocity-engine-core</artifactId>
<version>2.3</version>
</dependency>
模板的使用后缀名是vm
html.vm
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
</body>
</html>
编写测试类进行测试生成一个html模板
import org.apache.velocity.Template;
import org.apache.velocity.VelocityContext;
import org.apache.velocity.app.Velocity;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;
import java.io.FileWriter;
import java.io.IOException;
import java.util.Properties;
@SpringBootTest
class CommonPowerApplicationTests {
@Test
void contextLoads() throws IOException {
//设置velocity的资源加载器
Properties prop = new Properties();
prop.put("file.resource.loader.class", "org.apache.velocity.runtime.resource.loader.ClasspathResourceLoader");
//初始化velocity引擎
Velocity.init(prop);
//创建velocity容器
VelocityContext context = new VelocityContext();
context.put("name","张三");
//加载velocity模板文件
Template template = Velocity.getTemplate("templates/html.vm","UTF-8");
//合并数据到模板
FileWriter fw = new FileWriter("C:\\Users\\MI\\Desktop\\ruoyi\\yy-power\\src\\main\\resources\\html\\html.html");
template.merge(context,fw);
//释放资源
fw.close();
}
}
VTL注释
注释允许在模板中包含描述文字,而这些文字不会被放置到模板引擎的输出中。注释是一种有效的提醒自己和向别人解释你的VTL语句要做什么事情的方法。你也可以把注释用来做其他你认为有用的用途。下面就是一个注释的例子。
语法
行注释
## 注释内容
块注释
#*
块注释内容1
块注释内容2
*#
文档注释
#**
文档注释内容1
文档注释内容2
*#
VTL非解析内容
#[[ 非解析内容1 非解析内容2 ]]#
VTL变量引用
$变量名,若上下文没有对应的变量,则输出字符串”$变量名“
${变量名}, 若上下文中没有对应的变量,则输出字符串”${变量名}“
$!变量名,若上下文中没有对应的变量,则输出空字符串""
$!{变量名},若上下文中没有对应的变量,则输出空字符串""
VTL变量
常规变量:$name
正规语法:${name}
##以上二种,如果获取的变量不存在,在原样显示表达式,如果想展示为”“,可以使用$!变量名
常规变量:$!name
正规语法:$!{name}
测试类中ontext.put("name","张三");引用了变量。注释后第二种变量会为空第一种则会打印$name
VTL方法的引用
写一个实体类
public class User {
private String username;
private String password;
private String email;
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;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
}
使用测试类进行引用
常规语法:$user.username ------$user.password----$user.email
正规语法:${user.username} ------${user.password}----${user.email}
常规语法:$!user.username ------$!user.password----$!user.email
正规语法:$!{user.username} ------$!{user.password}----$!{user.email}
方法引用
方法引用实际就是指方法调用操作,关注点和参数方法的返回值将输出到最终的结果中
语法
方法的引用
常规写法: $str ----$now
正规写法: ${str} ----${now}
常规写法: $str.split("")---$now.getTime(),
正规写法: ${str.split("")}---------${now.getTime()}
方法的引用
常规写法: $str ----$now
正规写法: ${str} ----${now}
常规写法: $str.split(" ")---$now.getTime(),
正规写法: ${str.split(" ")}---------${now.getTime()}
常规写法: $str.split(" ")---$now.getTime(),
正规写法: ${str.split(" ")}---------${now.getTime()}
常规写法: $!str.split1(" ")---$!now1.getTime()
正规写法: $!{str.split1(" ")}---------$!{now1.getTime()}
测试类的使用
@Test
public void contextLoads() throws IOException {
//设置velocity的资源加载器
Properties prop = new Properties();
prop.put("file.resource.loader.class", "org.apache.velocity.runtime.resource.loader.ClasspathResourceLoader");
//初始化velocity引擎
Velocity.init(prop);
//创建velocity容器
VelocityContext context = new VelocityContext();
context.put("str","hello word velocity !");
context.put("now",new Date());
/*
User user = new User();
user.setUsername("张三");
user.setPassword("123456");
user.setEmail("zhangsan@163.com");
context.put("user",user);
*/
//context.put("name","张三");
//加载velocity模板文件
Template template = Velocity.getTemplate("templates/html.vm","UTF-8");
//合并数据到模板
FileWriter fw = new FileWriter("C:\\Users\\MI\\Desktop\\ruoyi\\yy-power\\src\\main\\resources\\html\\html.html");
template.merge(context,fw);
//释放资源
fw.close();
}
VIT指令----#set
指令主要用于定义重要模块,引用外部资源、流程控制、指令以#作为起始字符
流程控制
#set
作用:在页面中声明定义变量
语法:#set($变量=值)
示例
#获取set指令定义的变量
字符串: $str -----${str}
字符串: $str2 -----${str2}
整形: $int -----${int}
数组类型: $arr -----${arr}
布尔类型: $boolean -----${boolean}
map.key1: $map.key1----${map.key1}
map.key2: $map.key2----${map.key2}
map.key3: $map.key3----${map.key3}
#if
#set($language="java")
#if($language.equals("java"))
java开发工程师
#elseif($language.equals("php"))
php开发工程师
#else
开发工程师
#end
#foreach
作用遍历循环数组和集合
格式:
#foreach($item in $items) ...... [#break] #end $items:需要遍历的对象和集合 如果items的类型为map集合,那么遍历的是map的value $item 变量名称,代表遍历的每一项 #break 退出循环 内置属性: $foreach.index 获取遍历的索引,从0开始 $foreach.count 获取遍历的次数,从1开始
测试类的使用
@SpringBootTest
class CommonPowerApplicationTests {
@Test
public void contextLoads() throws IOException {
//设置velocity的资源加载器
Properties prop = new Properties();
prop.put("file.resource.loader.class", "org.apache.velocity.runtime.resource.loader.ClasspathResourceLoader");
//初始化velocity引擎
Velocity.init(prop);
//创建velocity容器
VelocityContext context = new VelocityContext();
context.put("str","hello word velocity !");
context.put("now",new Date());
//context.put("name","张三");//初始化输出直接写死
/*
//使用实体类的优势可以从数据库获取
User user = new User();
user.setUsername("张三");
user.setPassword("123456");
user.setEmail("zhangsan@163.com");
context.put("user",user);
*/
//循环一个集合
//字符串数据
String[] hobbies = new String[]{"eat", "drink", "play", "happy"};
context.put("hobbies",hobbies);
//对象集合
ArrayList<User> list = new ArrayList<>();
list.add(new User("yangguo","123456","yangguo@163.com"));
list.add(new User("xiaolongnv","123456","xiaolongnv@163.com"));
list.add(new User("guofurong","123456","guofurong@163.com"));
list.add(new User("lisi","123456","lisi@163.com"));
context.put("list",list);
//map
HashMap<String, Object> map = new HashMap<>();
map.put("key1","value1");
map.put("key2","value2");
map.put("key3","value3");
map.put("key4","value4");
context.put("map",map);
//加载velocity模板文件
Template template = Velocity.getTemplate("templates/html.vm","UTF-8");
//合并数据到模板
FileWriter fw = new FileWriter("C:\\Users\\MI\\Desktop\\ruoyi\\yy-power\\src\\main\\resources\\html\\html.html");
template.merge(context,fw);
//释放资源
fw.close();
}
}
示例:
##使用
<h1>遍历字符串数组</h1>
##查询字符串数组
#foreach($hobby in $hobbies)
$foreach.index----$foreach.count----$hobby
#end
<h1>遍历对象集合</h1>
<table border="1px">
<tr>
<td>编码</td>
<td>用户名</td>
<td>密码</td>
<td>邮箱</td>
<td>操作</td>
</tr>
#foreach($user in $list)
<tr>
<td>$foreach.count</td>
<td>$user.username</td>
<td>$user.password</td>
<td>$user.email</td>
<td>
<a href="">编辑</a>
<a href="">删除</a>
</td>
</tr>
#end
'</table>
<h1>遍历map集合</h1>
<h2>遍历值</h2>
#foreach($value in $map)
$value
#end
<h2>遍历键值对</h2>
#foreach($entry in $map.entrySet())
$entry.key ------$entry.value
#end
#include指令
#include
作用:引入外部资源,引入的资源不会被引擎解析
语法:
#include(resource) resource以为单引号或者双引号的字符串,也可以为$变量,内容为外部资源路径 注意的是:如果路径为相对路径,则引擎配置的文件加载路径作为参考
示例
#include("templates/html.vm")
#parse
作用:引入外部资源,引用的资源被引擎所解析
语法:
#parse(resource) resource以为单引号或者双引号的字符串,也可以为$变量,内容为外部资源路径 注意的是:如果路径为相对路径,则引擎配置的文件加载路径作为参考
示例:
#parse("templates/html.vm")
#define
作用:定义重用模板(不带参数)
语法:
#define($模块名称) 模板内容 #end
示例:
#define($table)
<table border="1px">
<tr>
<td>编码</td>
<td>用户名</td>
<td>密码</td>
<td>邮箱</td>
<td>操作</td>
</tr>
<tr>
<td>1</td>
<td>yangguo</td>
<td>123456</td>
<td>yangguo@163.com</td>
<td>
<a href="">编辑</a>
<a href="">删除</a>
</td>
</tr>
<tr>
<td>2</td>
<td>xiaolongnv</td>
<td>123456</td>
<td>xiaolongnv@163.com</td>
<td>
<a href="">编辑</a>
<a href="">删除</a>
</td>
</tr>
<tr>
<td>3</td>
<td>guofurong</td>
<td>123456</td>
<td>guofurong@163.com</td>
<td>
<a href="">编辑</a>
<a href="">删除</a>
</td>
</tr>
<tr>
<td>4</td>
<td>lisi</td>
<td>123456</td>
<td>lisi@163.com</td>
<td>
<a href="">编辑</a>
<a href="">删除</a>
</td>
</tr>
</table>
#end
##引用定义好的模块
$table
$table
$table
$table
#evaluate
语法:
<h1>动态计算</h1> #set($name="over") #evaluate("#if($name=='over') over #else not over #end") #if($name=='over') over #else not over #endc
测试类
@Test
public void test5() throws IOException {
//设置velocity的资源加载器
Properties prop = new Properties();
prop.put("file.resource.loader.class", "org.apache.velocity.runtime.resource.loader.ClasspathResourceLoader");
//初始化velocity引擎
Velocity.init(prop);
//创建velocity容器
VelocityContext context = new VelocityContext();
context.put("code","#if($language.equals(\"java\"))java开发工程师#elseif($language.equals(\"php\"))php开发工程师#else开发工程师#end");
//加载velocity模板文件
Template template = Velocity.getTemplate("templates/cs.vm","UTF-8");
//合并数据到模板
FileWriter fw = new FileWriter("C:\\Users\\MI\\Desktop\\ruoyi\\yy-power\\src\\main\\resources\\html\\cs.html");
template.merge(context,fw);
//释放资源
fw.close();
}
vm的用法
#evaluate($code)
宏指令
作用:定义重用模块(可带参数)
语法:
定义语法:
#macro(宏名[$arg]?) ........ #end
调用语法:
#宏名([$arg]?)
示例:
测试类的用法
@Test
public void test6() throws IOException {
//设置velocity的资源加载器
Properties prop = new Properties();
prop.put("file.resource.loader.class", "org.apache.velocity.runtime.resource.loader.ClasspathResourceLoader");
//初始化velocity引擎
Velocity.init(prop);
//创建velocity容器
VelocityContext context = new VelocityContext();
//对象集合
ArrayList<User> list = new ArrayList<>();
list.add(new User("yangguo","123456","yangguo@163.com"));
list.add(new User("xiaolongnv","123456","xiaolongnv@163.com"));
list.add(new User("guofurong","123456","guofurong@163.com"));
list.add(new User("lisi","123456","lisi@163.com"));
context.put("list",list);
//加载velocity模板文件
Template template = Velocity.getTemplate("templates/cs3.vm","UTF-8");
//合并数据到模板
FileWriter fw = new FileWriter("C:\\Users\\MI\\Desktop\\ruoyi\\yy-power\\src\\main\\resources\\html\\cs3.html");
template.merge(context,fw);
//释放资源
fw.close();
}
}
vm的用法
#macro(table $list)
<table border="1px">
<tr>
<td>编码</td>
<td>用户名</td>
<td>密码</td>
<td>邮箱</td>
<td>操作</td>
</tr>
#foreach ($user in $list)
<tr>
<td>$foreach.count</td>
<td>$user.username</td>
<td>$user.password</td>
<td>$user.email</td>
<td>
<a href="">编辑</a>
<a href="">删除</a>
</td>
</tr>
#end
</table>
#end
## 引用定义好的模块
#table($list)
VelocityTools使用
我们已经知道了velocity的基础知识,现在有一个工具包,VelocityTools
GenericTools 使用
什么叫做GenericTools
总之就是工具类,我们学习这个,就是学习这个工具类的api
搭建环境
<!-- velocity 的核心包-->
<dependency>
<groupId>org.apache.velocity</groupId>
<artifactId>velocity-engine-core</artifactId>
<version>2.2</version>
</dependency>
<!-- velocity 的工具包 要使用人家工具包里面的api,就需要导入工具包-->
<dependency>
<groupId>org.apache.velocity.tools</groupId>
<artifactId>velocity-tools-generic</artifactId>
<version>3.0</version>
</dependency>
快速入门
项目中已经导入了依赖,我们自己创建一个模板,在这个模板里面就可以使用工具类了。
我们查看工具类的文档,现在我们要在模板里面定义事件,那么在工具类的api里面找到相关事件的类。
这个文档里面有很多的类,每一个类里面有很多的方法,我们就是使用这个类里面的方法
比如这个时间,就是一个类,这个类里面有很多的方法
这个类里面的一些方法是
使用步骤:
写一个vm,里面使用工具类
写一个配置的xml
写测试方法
public class ToolsTest {
public static void main(String[] args) throws IOException {
// 1 创建引擎对象
VelocityEngine engine = new VelocityEngine();
// 2 设置模板的加载路径
engine.setProperty(Velocity.RESOURCE_LOADER,"class");
engine.setProperty("class.resource.loader.class","org.apache.velocity.runtime.resource.loader.ClasspathResourceLoader");
// 3 初始化引擎
engine.init();
// 4 加载tools.xml配置文件
ToolManager toolManager = new ToolManager();
toolManager.configure("tools.xml");
// 5 加载模板
Template template = engine.getTemplate("vm/tools.vm");
// 6 设置数据
ToolContext context = toolManager.createContext();
context.put("now",new Date());
// 7 合并数据到模板
FileWriter fileWriter = new FileWriter("E:\\java_springboot_code\\springboot_first\\01_springboot_mybatis\\src\\main\\resources\\vm\\tools.html");
template.merge(context,fileWriter);
// 8 释放资源
fileWriter.close();
}
}
最后生成的html 是

工具类以及案例
DateTool
## $data 就是VelocityTool 的key,也就是工具类里面的类名
当前时间: $date.get('yyyy-M-d H:m:s')
年:$date.getYear()
月:$date.getMonth()
日:$date.getDay()
年:$date.getYear($now)
月:$date.getMonth($now)
日:$date.getDay($now)
当前时间: $date.getDate()
当前时间: $date.get('yyyy-M-d H:m:s')
格式化时间: $date.format($now)
$date.format("yyyy/MM/dd",$now)
最后生成的HTML是
NumberTool
<?xml version="1.0" encoding="UTF-8"?>
<tools>
<toolbox scope = "application">
<tool class="org.apache.velocity.tools.generic.DateTool" format = "yyyy-MM-dd"> </tool>
<tool class="org.apache.velocity.tools.generic.NumberTool" > </tool>
</toolbox>
</tools>
原始数据: $mynumber
## $number 工具类 里面有很多的方法
格式化: $number.format($mynumber)
取整: $number.integer($mynumber)
将字符串转为number $number.toNumber($mynumber1)
MathTool
在模板里面要对这两个数据进行运算
num1+num2 = $math.add($num1,$num2)
num1-num2 = $math.sub($num1,$num2)
num1*num2 = $math.mul($num1,$num2)
num1/num2 = $math.div($num1,$num2)
向上取整: $math.ceil($num3)
向下取整: $math.floor($num3)
DisplayTool
默认输出格式: $display.list($list)
自定义分隔符 $display.list($list,',')
字符串截取 默认30个长度 $display.truncate($str)
$display.truncate($str,10)
$display.truncate($str,10,"10")
## alt 方法用于判断给的数据是否为空,如果为空,展示默认值
不为空: $display.alt($num1,"hhhh")
EscapeTool
$esc.velocity($HTML)
$esc.html($HTML)
$esc.url($HTML)
<tool class="org.apache.velocity.tools.generic.EscapeTool" > </tool>
FieldTool
<tool class="org.apache.velocity.tools.generic.FieldTool"
include="com.pojo.User" > </tool>
我们还可以在context里面存对象,之后利用这个工具,获取到这个对象里面的静态变量
ClassTool
ContextTool
这个就是帮助我们拿到在context里面存的数据
<tools>
<toolbox scope = "application">
<tool class="org.apache.velocity.tools.generic.DateTool" format = "yyyy-MM-dd"> </tool>
<tool class="org.apache.velocity.tools.generic.NumberTool" > </tool>
<tool class="org.apache.velocity.tools.generic.MathTool" > </tool>
<tool class="org.apache.velocity.tools.generic.DisplayTool" > </tool>
<tool class="org.apache.velocity.tools.generic.EscapeTool" > </tool>
<tool class="org.apache.velocity.tools.generic.FieldTool" include="com.pojo.User" > </tool>
</toolbox>
ContextTool 对于这个工具,必须放到这个request里面才可以生效
<toolbox scope="request">
<tool class="org.apache.velocity.tools.generic.ContextTool" > </tool>
</toolbox>
</tools>
获取到context中所有的key: $context.keys
获取到context中所有的value:$context.values
获取到所有的key-value 值
#foreach($key in $context.keys)
$key ---- $context.get($key)
#end

RenderTool
这个工具的意思是,我们自己在这个页面定义的数据,如果表达式变为字符串了,就不能执行了,现在想要将字符串的表达式进行执行,那么就可以使用这个工具
<tools>
<toolbox scope = "application">
<tool class="org.apache.velocity.tools.generic.DateTool" format = "yyyy-MM-dd"> </tool>
<tool class="org.apache.velocity.tools.generic.NumberTool" > </tool>
<tool class="org.apache.velocity.tools.generic.MathTool" > </tool>
<tool class="org.apache.velocity.tools.generic.DisplayTool" > </tool>
<tool class="org.apache.velocity.tools.generic.EscapeTool" > </tool>
<tool class="org.apache.velocity.tools.generic.FieldTool" include="com.pojo.User" > </tool>
</toolbox>
<toolbox scope="request">
<tool class="org.apache.velocity.tools.generic.ContextTool" > </tool>
<tool class="org.apache.velocity.tools.generic.RenderTool" > </tool>
</toolbox>
</tools>
##定义一个list集合
#set($list=[1,2,2,3])
## 设置变量为一个字符串
#set($object = '$list')
#set($method = 'size()')
##获取集合的长度
$render.eval("$object.$method")
生成的为
SortTool
先往context里面存放list集合数据,里面的数据是杂乱无章的
<tool class="org.apache.velocity.tools.generic.SortTool" > </tool>
以上是有序的
以上对于对象是默认升序的,现在我们想要降序咋办
CollectionTool
除了有SortTool 的方法功能,还有
将字符串根据某个规则 生成为集合
#set($str="44,88,99")
$str.split(",")
XmlTool
创建一个xml