一、了解Velocity
JSP、Freemarker、Velocity并称3大模版技术
下面是JSP
、Freemarker
和Velocity
的简要对比表格:
特性/技术 | JSP | Freemarker | Velocity |
---|---|---|---|
设计目标 | 视图层技术,与Servlet结合 | 模板引擎,用于生成HTML | 模板引擎,用于生成各种文本输出 |
与Java集成 | 紧密集成,可以直接编写Java代码 | 松散集成,通过模板变量和表达式访问数据 | 松散集成,通过模板变量和表达式访问数据 |
语法 | 类似HTML的XML语法,可嵌入Java代码 | 自定义模板语言,简洁易懂 | 自定义模板语言,类似Freemarker |
性能 | 编译后性能较好,但初次加载较慢 | 编译后性能优秀,初次加载较快 | 编译后性能较好,初次加载中等 |
指令 | 指令如<jsp:include> 、<jsp:forward> 等 | 自定义指令,如<#assign> 、<#if> 等 | 自定义指令,如#set 、#if 等 |
表达式 | 支持EL表达式和JSTL标签库 | 支持丰富的表达式和函数 | 支持表达式和宏定义 |
错误处理 | 依赖于Java异常处理 | 自定义错误处理机制 | 自定义错误处理机制 |
学习曲线 | 较高,需要了解Java和JSP语法 | 较低,专注于模板编写 | 较低,专注于模板编写 |
应用场景 | Java Web应用程序 | 报告、邮件模板、Web页面等 | 报告、邮件模板、Web页面等 |
这个表格提供了一个简要的对比,但请注意,每个技术都有其独特的优点和适用场景。在选择使用哪种技术时,应考虑到项目的具体需求、团队的技术栈和偏好,以及技术的长期维护性和社区支持等因素。
二、入门:编写Velocity的DEMO
velocity 使用不依赖于于springboot
<!--velocity代码生成使用模板 -->
<dependency>
<groupId>org.apache.velocity</groupId>
<artifactId>velocity-engine-core</artifactId>
</dependency>
2.1编写测试DEMO:
类位置:ruoyi-admin/src/test/java/com/ruoyi/test/utilTest/VelocityTest.java
test 测试文件下新建测试类
如下面测试类4个步骤:加载模版并将数据合并到模版
package com.ruoyi.test.utilTest;
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;
/**
* <简述>
* <详细描述>
*
* @author syf
* @date 2024年06月27日 9:33
*/
@SpringBootTest
public class VelocityTest {
@Test
public void test1() throws IOException {
//1-设置velocity资源加载器
Properties prop = new Properties();
prop.put("file.resource.loader.class", "org.apache.velocity.runtime.resource.loader.ClasspathResourceLoader");
Velocity.init(prop);
//2-创建Velocity容器
VelocityContext context = new VelocityContext();
context.put("name", "张三");
//3-加载模板
Template tpl = Velocity.getTemplate("vm/index.vm", "UTF-8");
FileWriter fw = new FileWriter("D:\\Git\\repository\\ruoyi-vue-plus-syf-4.x\\ruoyi-admin\\src\\main\\resources\\vm\\syf.html");
//合并数据到模板
tpl.merge(context, fw);
//释放资源
fw.close();
}
}
模版:
位置:ruoyi-admin/src/main/resources/vm/index.vm
resources目录下新建文件夹个文件
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
hello , ${name} !
</body>
</html>
2.2 结果:
生成文件如下
三. 基础语法以及实际代码展示
vm模版语法
1-11个示例,包含:注
释写法、变量获取、set变量定义、集合遍历、模版引入解析、宏定义
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
## 1- 这是注释行
#*
2- 这是注释块(类似JAVA /* */)
*#
## 3- 这是变量 ${name}
#[[3- ${name} :]]# ${name}
## 3-1 以下写法的含义代表么如果有变量, 那么获取变量值展示, 没有变量展示""
#[[3-1 $!{name} :]]# $!{name}
## 4-非解析内容(原样输出) #[[ ]]#
#[[4- ${name} 值是:]]# ${name} !
##5- 属性引用
#[[5-${sysUser.userName} 值是:]]# ${sysUser.userName} !
##5-1 属性引用, 成员方法调用
#[[5-1 ${sysUser.nickName.split(',')} 值是:]]# ${sysUser.nickName.split(',')} !
#[[5-1 ${sysUser.nickName.split(',')[0]} 值是:]]# ${sysUser.nickName.split(',')[0]} !
##6- set定义变量 #set($变量 = 值)
<h1>6-打印set指令定义的变量</h1>
#set($str = "hello world")
#set($int = 1)
#set($arr = [1,2,3,4])
#set($boolean = true)
#set($map = {"key1":"value1", "key2":"value2"})
## 在字符串中也可以引用之前定义过的变量
#set($str2 = "$str , how are you !")
#set($str3 = '$str , how are you !')
#[[ ${str} ]]# ${str}
#[[ ${int} ]]# ${int}
#[[ ${arr} ]]# ${arr}
#[[ ${boolean} ]]# ${boolean}
#[[ ${map.key1}--${map.key2}]]# ${map.key1}--${map.key2}
#[[ ${str2} ]]# ${str2}
#[[ ${str3} ]]# ${str3}
##7-逻辑判断 #if(判断条件) #elseif(判断条件) #else #end
<h1>7-逻辑判断</h1>
#set(${val} = 1)
#if(${val} == 1)
#[[ 进入1判断 ]]#
#elseif(${val} == 2)
#[[ 进入2判断 ]]#
#else
#[[ 进入3判断 ]]#
#end
<h1>8-循环</h1>
##8-循环 #foreach($item in $items)
## ..........
## [#break]
## #end
<h1>遍历数组</h1>
#foreach($en in $arr )
${foreach.index} -- ${en} <br>
#end
<h1>变量对象集合</h1>
<table>
<tr>
<td>编号</td>
<td>用户名</td>
<td>密码</td>
<td>昵称</td>
</tr>
#foreach($user in $users)
<tr>
<td>${foreach.index}</td>
<td>${user.userName}</td>
<td>${user.password}</td>
<td>${user.nickName}</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
<h1>9-引入模板</h1>
##引入 include引入的模板不会进行解析
#include("vm/index2.vm")
<h1>10-引入模板</h1>
##引入外部资源 , 将被引擎所解析
#parse("vm/index2.vm")
<h1>11-动态计算 :可以让我们在字符串中使用变量</h1>
#set($booklean = "over")
#evaluate("#if($booklean=='over') yes #else no #end")
<h1>12-宏定义</h1>
#macro(table $users)
#foreach($user in $users)
<tr>
<td>${foreach.index}</td>
<td>${user.userName}</td>
<td>${user.password}</td>
<td>${user.nickName}</td>
</tr>
#end
#end
<h1>调用宏</h1>
#table($users)
</body>
</html>
打印的结果集
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
3- ${name} : 张三
3-1 $!{name} : 张三
4- ${name} 值是: 张三 !
5-${sysUser.userName} 值是: 获取属性名称 !
5-1 ${sysUser.nickName.split(',')} 值是: [java, Velocity, vue] !
5-1 ${sysUser.nickName.split(',')[0]} 值是: java !
<h1>6-打印set指令定义的变量</h1>
${str} hello world
${int} 1
${arr} [1, 2, 3, 4]
${boolean} true
${map.key1}--${map.key2} value1--value2
${str2} hello world , how are you !
${str3} $str , how are you !
<h1>7-逻辑判断</h1>
进入1判断
<h1>8-循环</h1>
<h1>遍历数组</h1>
0 -- 1 <br>
1 -- 2 <br>
2 -- 3 <br>
3 -- 4 <br>
<h1>变量对象集合</h1>
<table>
<tr>
<td>编号</td>
<td>用户名</td>
<td>密码</td>
<td>昵称</td>
</tr>
<tr>
<td>0</td>
<td>获取属性名称</td>
<td>12345678</td>
<td>java,Velocity,vue</td>
</tr>
<tr>
<td>1</td>
<td>获取属性名称</td>
<td>12345678</td>
<td>java,Velocity,vue</td>
</tr>
<tr>
<td>2</td>
<td>获取属性名称</td>
<td>12345678</td>
<td>java,Velocity,vue</td>
</tr>
<tr>
<td>3</td>
<td>获取属性名称</td>
<td>12345678</td>
<td>java,Velocity,vue</td>
</tr>
</table>
<h1>遍历map集合</h1>
<h2>遍历值</h2>
value1
value2
<h2>遍历键值对</h2>
key1 -- value1
key2 -- value2
<h1>9-引入模板</h1>
${name}
<h1>10-引入模板</h1>
张三
<h1>11-动态计算 :可以让我们在字符串中使用变量</h1>
yes
<h1>12-宏定义</h1>
<h1>调用宏</h1>
<tr>
<td>0</td>
<td>获取属性名称</td>
<td>12345678</td>
<td>java,Velocity,vue</td>
</tr>
<tr>
<td>1</td>
<td>获取属性名称</td>
<td>12345678</td>
<td>java,Velocity,vue</td>
</tr>
<tr>
<td>2</td>
<td>获取属性名称</td>
<td>12345678</td>
<td>java,Velocity,vue</td>
</tr>
<tr>
<td>3</td>
<td>获取属性名称</td>
<td>12345678</td>
<td>java,Velocity,vue</td>
</tr>
</body>
</html>
后台JAVA数据模版合并:
package com.ruoyi.test.utilTest;
import com.ruoyi.common.core.domain.entity.SysUser;
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.ArrayList;
import java.util.List;
import java.util.Properties;
/**
* <简述>
* <详细描述>
*
* @author syf
* @date 2024年06月27日 9:33
*/
@SpringBootTest
public class VelocityTest {
@Test
public void test1() throws IOException {
//1-设置velocity资源加载器
Properties prop = new Properties();
prop.put("file.resource.loader.class", "org.apache.velocity.runtime.resource.loader.ClasspathResourceLoader");
Velocity.init(prop);
//2-创建Velocity容器
VelocityContext context = new VelocityContext();
context.put("name", "张三");
//对象
SysUser sysUser = new SysUser();
sysUser.setUserName("获取属性名称");
sysUser.setNickName("java,Velocity,vue");
sysUser.setPassword("12345678");
context.put("sysUser", sysUser);
//
List<SysUser> list = new ArrayList<>();
list.add(sysUser);
list.add(sysUser);
list.add(sysUser);
list.add(sysUser);
context.put("users", list);
//3-加载模板
Template tpl = Velocity.getTemplate("vm/index.vm", "UTF-8");
FileWriter fw = new FileWriter("D:\\Git\\repository\\ruoyi-vue-plus-syf-4.x\\ruoyi-admin\\src\\main\\resources\\vm\\syf.html");
//合并数据到模板
tpl.merge(context, fw);
//释放资源
fw.close();
}
}