一. velocity 简介
1、velocity简介
velocity 是一个基于Java的模板引擎,可以通过特定的语法获取在java对象的数据,填充到模板中,从而实现界面与java代码的分离
2、应用场景
- Web引用程序:作为引用程序的视图,展示数据
- 源代码生成:Velocity 可用于基于模板生成java源代码
- 自动 电子邮件:网站注册,认证等的电子邮件模板
- 网页静态化:基于velocity 模板,生成静态网页
3、velocity 组成结构
Velocity主要分为app、content、runtime 和一些辅助util几个部分
- app模块:主要封装了一些接口,暴露给使用者使用。主要有两个类,分别是Velocity(单例)和VelocityEngine
- context模块:主要封装了模板渲染需要使用的变量
- Runtime模块:整个Velocity的核心模块,Runtime模块会将加载的模板解析成语法树,Velocity调用mergeTemplate方法时会渲染整棵树,并输出最终的渲染结果
- RuntimeInstance类为整个Velocity渲染提供了一个单例模式,拿到了这个实例就可以完成渲染过程了
二. 快速入门
1、需求分析
使用Velocity定义html模板,将动态数据填充到模板中,形成一个完整的html页面
2、步骤
- 创建项目(maven)
- 引入依赖
- 定义模板
- 输出html
3、案例
pom文件加入依赖
<dependency>
<groupId>org.apache.velocity</groupId>
<artifactId>velocity-engine-core</artifactId>
<version>2.2</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<scope>test</scope>
</dependency>
在resources下创建html模板文件 start.html.vm
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title> ${title}</title>
</head>
<body>
hello , ${name} !
</body>
</html>
编写代码,生成
public class Test1 {
@Test
public void test1() throws IOException {
// 1、设置velocity的资源加载器
Properties properties = new Properties();
properties.put("file.resource.loader.class", "org.apache.velocity.runtime.resource.loader.ClasspathResourceLoader");
// 2、初始化velocity引擎
Velocity.init(properties);
// 3、创建velocity容器
VelocityContext context = new VelocityContext();
context.put("name", "velocity");
context.put("title", "hello");
// 4、加载velocity模板文件
Template template = Velocity.getTemplate("vms/start.html.vm", "utf-8");
// 5、合并数据到模板
FileWriter fileWriter = new FileWriter("D:\\code\\summary\\src\\main\\resources\\templates\\start.html");
template.merge(context, fileWriter);
// 6、释放资源
fileWriter.close();
}
}
三.基础语法
1、VTL介绍
Velocity Template Language(VTL),是Velocity中提供的一种模板语言,旨在提供最简单和最干净的方法来将动态内容合并到网页中,简单来说VTL可以将程序中的动态数展示到网页中
VTL的语句分为4大类:注释
,非解析内容
,引用
和指令
。
2、VTL 注释
2.1、语法
1. 行注释
## 这是行注释内容 ,注释的内容不会被输出, 但会有一些空行
2. 块注释
#*
块注释内容1
块注释内容2
*#
3. 文档注释
#**
文档注释内容1
文档注释内容2
*#
3、非解析内容
所谓非解析内容也就是不会被引擎解析的内容。
3.1、语法
#[[
非解析内容1
非解析内容2
]]#
4、引用
4.1 变量引用
引用语句就是对引擎上下文对象中的属性进行操作。语法方面分为常规语法(%E5%92%8C%E6%AD%A3%E8%A7%84%E8%AF%AD%E6%B3%95(#card=math&code=%E5%B1%9E%E6%80%A7%29%E5%92%8C%E6%AD%A3%E8%A7%84%E8%AF%AD%E6%B3%95%28){属性})
4.1.1 语法
$变量名,若上下问中没有对应的变量,则输出字符串"$变量名"
${变量名},若上下文中没有对应的变量,则输出字符串"${变量名}"
$!变量名,若上下文中没有对应的变量,则输出空字符串""
$!{变量名},若上下文中没有对应的变量,则输出空字符串""
4.1.2 示例
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title> ${title}</title>
</head>
<body>
hello , ${name} !
引用变量
常规语法:$name
正规语法:${name}
## 如果读取的变量不存在,表达式会原样展示,如果不想展示,可以使用$!变量名
## 一下写法的含义代表如果有变量,那么获取变量值展示,没有变量展示""
常规语法: $age
正规语法: ${age}
常规语法: $!age
正规语法: $!{age}
</body>
</html>
4.2属性引用
4.2.1 语法
$变量名.属性,若上下问中没有对应的变量,则输出字符串"$变量名.属性"
${变量名.属性},若上下文中没有对应的变量,则输出字符串"${变量名.属性}"
$!变量名.属性,若上下文中没有对应的变量,则输出空字符串""
$!{变量名.属性},若上下文中没有对应的变量,则输出空字符串""
4.2.2 示例
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title> Title</title>
</head>
<body>
属性引用
常规语法: $user.name
正规语法: ${user.name}
常规语法: $!user.name
正规语法: $!{user.name}
</body>
</html>
4.3、方法引用
方法引用实际就是指方法调用操作,关注点返回值和参数,方法的返回值将输出到最终结果中
4.3.1 语法
$变量名.方法([入参1[, 入参2]*]?) 常规写法
${变量名.方法([入参1[, 入参2]*]?)} 正规写法
$!变量名.方法([入参1[, 入参2]*]?) 常规写法
$!{变量名.方法([入参1[, 入参2]*]?)} 正规写法
4.3.2 示例
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title> Title</title>
</head>
<body>
方法引用
$name.split(" ")
${name.split(" ")}
$time.getTime()
${time.getTime()}
</body>
</html>
5、指令
指令主要用于定义重用模块、引入外部资源、流程控制。指令以#
作为起始符
5.1 流程控制
#set
作用: 在页面中声明定义变量
语法: #set($变量 = 值)
示例
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title> Title</title>
</head>
<body>
set 指令
#set($str = "hello world!")
#set($int = 1)
#set($arr= [1,2])
#set($boolean = true)
#set($map = {"key1":"value2", "key2":"value2"})
## 在字符串中也可以引用之前定义过的变量
#set($str2 = "$str , how are you!")
#set($str3 = "$str2, how are you!")
获取set定义的属性
$str
$int
$arr
$boolean
$map.key1 --- ${map.key2}
$str2
$str3
</body>
</html>
#if、#elseif、#else
作用:进行逻辑判断
语法:
#if(判断条件)
......
#elseif(判断条件)
......
#else
......
#end
示例
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title> Title</title>
</head>
<body>
ifelseif 指令
#set($language = "Java")
#if($language.equals("Java"))
Java开发工程师
#elseif($language.equals("html"))
前端工程师
#else
开发工程师
#end
</body>
</html>
#foreach
作用: 遍历循环数组或者集合
格式:
#foreach($item in $items)
.......
[#break]
#end
$items: 需要遍历的对象或者集合
如果items的类型为map集合,那么遍历的是map的value
$item : 变量名称,代表遍历的每一项
#break; 推出循环
内置属性
$foreach.index : 获取遍历的索引,从0开始
$foreach.count : 获取遍历的次数,从1开始
示例
@Test
public void test2() throws IOException {
// 1、设置velocity的资源加载器
Properties properties = new Properties();
properties.put("file.resource.loader.class", "org.apache.velocity.runtime.resource.loader.ClasspathResourceLoader");
// 2、初始化velocity引擎
Velocity.init(properties);
// 3、创建velocity容器
VelocityContext context = new VelocityContext();
context.put("hobbies", Arrays.asList("eat", "play", "sleep"));
List<Order> orders = new ArrayList<>();
orders.add(new Order("11111111111", 1, "订单1"));
orders.add(new Order("22222222222", 2, "订单2"));
orders.add(new Order("33333333333", 3, "订单3"));
orders.add(new Order("44444444444", 4, "订单4"));
context.put("orders", orders);
Map<String, Object> map = new HashMap<>();
map.put("phone", "1523556777");
map.put("key2", "value2");
map.put("key3", "value3");
context.put("map", map);
// 4、加载velocity模板文件
Template template = Velocity.getTemplate("vms/foreach.html.vm", "utf-8");
// 5、合并数据到模板
FileWriter fileWriter = new FileWriter("D:\\code\\summary\\src\\main\\resources\\templates\\foreach.html");
template.merge(context, fileWriter);
// 6、释放资源
fileWriter.close();
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title> Title</title>
</head>
<body>
foreach 指令
<ul>
#foreach($hobbie in $hobbies)
<li>
$foreach.index -- $hobbie -- $foreach.count
</li>
#end
</ul>
遍历对象集合
<table>
<tr>
<th>订单编号</th>
<th>数量</th>
<th>名称</th>
</tr>
#foreach($order in $orders)
<tr>
<td>$order.uuid</td>
<td>$order.count</td>
<td>$order.name</td>
</tr>
#end
</table>
遍历map集合
#foreach($value in $map)
$value
#end
<h2>遍历键值对</h2>
#foreach($entry in $map.entrySet())
$entry.key --- $entry.value
#end
</body>
</html>
5.2 引入资源
#include
作用:引入外部资源,引入的资源不会被引擎所解析
语法:#include(resource)
- resource可以为单引号或双引号的字符串,也可以是$变量,内容为外部资源路径。
- 注意:路径如果为相对路径,则以引擎配置的文件加载器加载路径作为参考
示例
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title> Title</title>
</head>
<body>
include
#include("/vms/start.html.vm")
</body>
</html>
#parse
作用:引入外部资源,引入的资源将被引擎所解析
语法:#parse(resource)
- resource 可以为单引号或双引号的字符串,也可以为$变量,内容为外部资源路径
- 注意:路径如果为相对路径,则以引擎配置的文件加载器加载路径作为参考系
示例
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title> Title</title>
</head>
<body>
include.html.vm
#parse("/vms/start.html.vm")
</body>
</html>
#define
作用:定义重用模块(不带参数)
语法:
#define($模块名称)
模块内容
#end
示例
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title> Title</title>
</head>
<body>
define
#define($table)
<table>
<tr>
<th>订单编号</th>
<th>数量</th>
<th>名称</th>
</tr>
<tr>
<td>11111111111</td>
<td>1</td>
<td>订单1</td>
</tr>
<tr>
<td>22222222222</td>
<td>2</td>
<td>订单2</td>
</tr>
<tr>
<td>33333333333</td>
<td>3</td>
<td>订单3</td>
</tr>
<tr>
<td>44444444444</td>
<td>4</td>
<td>订单4</td>
</tr>
</table>
#end
$table
$table
$table
$table
</body>
</html>
#evaluate
作用:动态计算,动态计算可以让我们在字符串中使用变量
语法:#evalute("计算语句")
示例
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title> Title</title>
</head>
<body>
evaluate 动态计算
#set($name = "over")
#evaluate("#if($name == 'over') over #else not over #end")
#if($name == 'over')
over
#else
not over
#end
</body>
</html>
5.3 宏指令
作用:定义重用模块(可带参数)
语法:
#macro(宏名 [$arg]?)
....
#end
调用语法
#宏名([$arg]?)
示例:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title> Title</title>
</head>
<body>
macro
#macro(table $list)
<table>
<tr>
<th>订单编号</th>
<th>数量</th>
<th>名称</th>
</tr>
#foreach($order in $list)
<tr>
<td>$order.uuid</td>
<td>$order.count</td>
<td>$order.name</td>
</tr>
#end
</table>
#end
#table($orders)
</body>
</html>
四.综合案例
自行发挥
标签:end,name,语法,velocity,变量名,模板
From: https://blog.51cto.com/lizp/8081009