velocity


一、介绍

1、简介

Velocity是一个基于Java的模板引擎,可以通过特定的语法获取在java对象的数据 , 填充到模板中,从而实现界面和java代码的分离 !

image-20230209142709442

Velocity解决了如何在后台程序和网页之间传递数据的问题,后台代码和视图之间相互独立,一方的修改不影响另一方 .

他们之间是通过环境变量(Context)来实现的,网页制作一方和后台程序一方相互约定好对所传递变量的命名约定,比如上个程序例子中的site, name变量,它们在网页上就是$name ,$site 。

只要双方约定好了变量名字,那么双方就可以独立工作了。无论页面如何变化,只要变量名不变,那么后台程序就无需改动,前台网页也可以任意由网页制作人员修改。这就是Velocity的工作原理。

2、应用场景

  • Web应用程序 : 作为为应用程序的视图, 展示数据。
  • 代码生成器 : Velocity可用于基于模板生成Java源代码
  • 自动电子邮件 : 网站注册 , 认证等的电子邮件模板
  • 网页静态化 : 基于velocity模板 , 生成静态网页

3、velocity 组成结构

image-20230209142822171

Velocity主要分为app、context、runtime和一些辅助util几个部分。

  • app模块 : 主要封装了一些接口 , 暴露给使用者使用。主要有两个类,分别是Velocity(单例)和VelocityEngine。

  • Context模块 : 主要封装了模板渲染需要的变量

  • Runtime模块 : 整个Velocity的核心模块,Runtime模块会将加载的模板解析成语法树,Velocity调用mergeTemplate方法时会渲染整棵树,并输出最终的渲染结果。

  • RuntimeInstance类为整个Velocity渲染提供了一个单例模式,拿到了这个实例就可以完成渲染过程了。

二、示例代码

1、依赖

<dependency>
    <groupId>org.apache.velocity</groupId>
    <artifactId>velocity-engine-core</artifactId>
    <version>2.2</version>
</dependency>

2、模板文件

在项目resources目录下创建模板文件 vm/test.html.vm

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>

hello , ${name} !

</body>
</html>

3、代码

import org.apache.velocity.Template;
import org.apache.velocity.VelocityContext;
import org.apache.velocity.app.Velocity;
import java.util.Properties;

@Test
public void test3() throws IOException {

    //设置velocity资源加载器
    Properties prop = new Properties();
    prop.put("file.resource.loader.class", "org.apache.velocity.runtime.resource.loader.ClasspathResourceLoader");
    Velocity.init(prop);

    //创建Velocity容器
    VelocityContext context = new VelocityContext();
    context.put("name", "rewind");

    //加载模板
    Template tpl = Velocity.getTemplate("vm/test.html.vm", "UTF-8");

    FileWriter fw  = new FileWriter("D:\\temp\\test.html");
    //合并数据到模板
    tpl.merge(context, fw);

    //释放资源
    fw.close();
}

4、输出文件

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>

hello , rewind !

</body>
</html>

三、基础语法

1、VTL介绍

Velocity Template Language (VTL) , 是Velocity 中提供的一种模版语言 , 旨在提供最简单和最干净的方法来将动态内容合并到网页中。简单来说VTL可以将程序中的动态数展示到网页中

VTL的语句分为4大类:注释 , 非解析内容 ** , **引用指令

2、VTL注释

行注释

## 行注释内容

块注释

#*
块注释内容1
块注释内容2
*#

文档注释

#**
文档注释内容1
文档注释内容2
*#

块注释和文档注释虽然均不输出到最终结果上,但会导致最终结果出现一行空行。使用行注释则不会出现此情况。

示例

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
## 我是行注释

#*
* 我是块注释
* 呵呵呵
* *#

#**
* 我是文档注释
*
* *#
hello , ${name} !

</body>
</html>

3、非解析内容

所谓非解析内容也就是不会被引擎解析的内容。

语法

#[[
非解析内容1
非解析内容2 
]]#

示例

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>

hello , ${name} !

<h1>非解析内容</h1>
#[[
直接输出的内容1
直接输出的内容2
${name}
]]#
</body>
</html>

4、引用

(1)变量引用

引用语句就是对引擎上下文对象中的属性进行操作。语法方面分为常规语法($属性)和正规语法(${属性})。

语法

$变量名, 若上下文中没有对应的变量,则输出字符串"$变量名"
${变量名},若上下文中没有对应的变量,则输出字符串"${变量名}" 
$!变量名, 若上下文中没有对应的变量,则输出空字符串"" 
$!{变量名}, 若上下文中没有对应的变量,则输出空字符串""

变量的命名规则:由字母、下划线(_)、破折号(-)和数字组成,而且以字母开头。

变量的数据类型为:

  • Integer、Long等简单数据类型的装箱类型;

  • String类型

  • Object子类

  • Object[] 数组类型,从1.6开始Velocity将数组类型视为 java.util.List 类型看待,因此模板中可调用 size() 、 get(int index) 和 isEmpty() 的变量方法;

  • java.util.Collection子类;

  • java.util.Map子类;

  • java.util.Iterator对象;

  • java.util.Enumeration对象。

示例

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<h1>引用变量</h1>
常规语法 : $name
正规语法 : ${name}

## 如果获取的变量不存在, 表达式会原样展示 , 如果不想展示 , 可以使用 $!变量名
## 以下写法的含义代表么如果有变量, 那么获取变量值展示, 没有变量展示""
常规语法 : $!name
正规语法 : $!{name}

</body>
</html>

(2)属性引用

语法

$变量名.属性,     若上下文中没有对应的变量,则输出字符串"$变量名.属性"
${变量名.属性}    若上下文中没有对应的变量,则输出字符串"${变量名.属性}"
$!变量名.属性    若上下文中没有对应的变量,则输出字符串""
$!{变量名.属性}    若上下文中没有对应的变量,则输出字符串""

示例

常规语法 : $user.username --- $user.password
正规语法 : ${user.username} --- ${user.password}

正规语法 : ${user.email} --- ${user.email}
正规语法 : $!{user.email} --- $!{user.email}

(3)方法引用

方法引用实际就是指方法调用操作,关注点返回值参数 , 方法的返回值将输出到最终结果中

语法

$变量名.方法([入参1[, 入参2]*]?), 常规写法
${变量名.方法([入参1[, 入参2]*]?)}, 正规写法

$!变量名.方法([入参1[, 入参2]*]?), 常规写法
$!{变量名.方法([入参1[, 入参2]*]?)}, 正规写法

示例

$str.split(" ")
${str.split(" ")}
$time.getTime()
${time.getTime()}

5、指令-流程控制

指令主要用于定义重用模块、引入外部资源、流程控制。指令以 # 作为起始字符。

(1)声明变量#set

作用 : 在页面中声明定义变量

语法: #set($变量 = 值)

#set($str = "hello world")
#set($int = 1)
#set($arr = [1,2])
#set($boolean = true)
#set($map = {"key1":"value1", "key2":"value2"})

## 在字符串中也可以引用之前定义过的变量
#set($str2 = "$str , how are you !")
#set($str3 = '$str , how are you !')


${str}
${int}
${arr}
${boolean}
${map.key1}--${map.key2}
${str2}
${str3}

(2)逻辑判断#if

语法

#if(判断条件)
  .........
#elseif(判断条件)
  .........
#else
  .........
#end 

示例

#set($language="PHP")

#if($language.equals("JAVA"))
    java开发工程师
#elseif($language.equals("PHP"))
    php开发工程师
#else
    开发工程师
#end

(3)循环#foreach

作用 : 遍历循环数组或者集合

语法

#foreach($item in $items)
    ..........
    [#break]
#end
  • $items : 需要遍历的对象或者集合
    • 如果items的类型为map集合, 那么遍历的是map的value
  • $item : 变量名称, 代表遍历的每一项
  • #break : 退出循环
  • 内置属性 :
    • $foreach.index : 获取遍历的索引 , 从0开始
    • $foreach.count : 获取遍历的次数 , 从1开始

示例

#foreach($str in $hobbies)
    ${foreach.index} -- ${str}
#end
 #foreach($user in $users)
    <tr>
        <td>${foreach.index}</td>
        <td>${user.username}</td>
        <td>${user.password}</td>
        <td>${user.email}</td>
        <td>${user.age}</td>
        <td>
            <a href="">编辑</a>
            <a href="">删除</a>
        </td>
    </tr>
#end
<h1>遍历map集合</h1>
<h2>遍历值</h2>
 #foreach($value in $map)
     $value
 #end

<h2>遍历键值对</h2>
#foreach($entry in $map.entrySet())
    $entry.key -- $entry.value
#end

6、指令-引入资源

(1)#include

作用 : 引入外部资源 , 引入的资源不会被引擎所解析

语法 : #include(resource)

  • resource可以为单引号或双引号的字符串,也可以为**$变量**,内容为外部资源路径。
  • 注意 : 路径如果为相对路径,则以引擎配置的文件加载器加载路径作为参考
#include("demo8.vm")

(2)#parse

作用 : 引入外部资源 , 引入的资源将被引擎所解析

语法 : #parse(resource)

  • resource可以为单引号或双引号的字符串,也可以为**$变量**,内容为外部资源路径。
  • 注意 : 路径如果为相对路径,则以引擎配置的文件加载器加载路径作为参考系
#parse("demo8.vm")

(3)#define

作用 : 定义重用模块(不带参数)

语法 :

#define($模块名称)
    模块内容
#end

示例

<h1>定义模块</h1>
#define($table)
<table border="1px" align="center">
    <tr>
        <td>编号</td>
        <td>用户名</td>
        <td>密码</td>
        <td>邮箱</td>
        <td>年龄</td>
        <td>操作</td>
    </tr>
</table>
#end

<h1>使用模块</h1>
$table
$table
$table

(4)#evaluate

作用 : 动态计算 , 动态计算可以让我们在字符串中使用变量

语法 : #evalute("计算语句")

#set($name = "over")

#evaluate("#if($name=='over') over  #else  not over #end")

#if($name=='over')
    over
#else
    not over
#end

7、宏指令

作用 : 定义重用模块(可带参数)

语法 :

定义语法

#macro(宏名 [$arg]?)
   .....
#end

调用语法

#宏名([$arg]?)

**示例 : **

#macro(table $list)
<table border="1px">
    <tr>
        <td>编号</td>
        <td>用户名</td>
        <td>密码</td>
        <td>邮箱</td>
        <td>年龄</td>
        <td>操作</td>
    </tr>
    #foreach($item in $list)
    <tr>
        <td>${foreach.count}</td>
        <td>${item.username}</td>
        <td>${item.password}</td>
        <td>${item.email}</td>
        <td>${item.age}</td>
        <td>
            <a href="">编辑</a>
            <a href="">删除</a>
        </td>
    </tr>
    #end
</table>
#end

<h1>调用宏</h1>
#table($users)

四、代码生成器

可以参考人人开源的代码生成器,更为完整

1、模板

package ${package}.service.impl;

import ${package}.dao.${className}Dao;
import ${package}.pojo.${className};
import ${package}.service.${className}Service;
import org.springframework.beans.factory.annotation.Autowired;

import java.util.Arrays;
import java.util.List;
import java.util.stream.Stream;

public class ${className}ServiceImpl  implements ${className}Service {

    @Autowired
    private ${className}Dao ${classname}Dao ;

    public List<${className}> list() {
        return ${classname}Dao.selectAll();
    }

    public void save(${className} ${classname}) {
            ${classname}Dao.insert(${classname});
    }

    public void update(${className} ${classname}) {
            ${classname}Dao.updateByPrimaryKey(${classname});
    }

    public void delete(Integer[] ids) {
        Stream.of(ids).forEach(${classname}Dao::deleteByPrimaryKey);
    }
}

2、生成代码

我们可以封装一个生成代码的工具类 , 后期生成代码运行工具类即可

import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.velocity.Template;
import org.apache.velocity.VelocityContext;
import org.apache.velocity.app.Velocity;

import java.io.File;
import java.io.IOException;
import java.io.StringWriter;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;

/**
 * 代码生成器   工具类
 */
public class GenUtils {

    private static String currentTableName;

    public static List<String> getTemplates() {
        List<String> templates = new ArrayList<String>();
        templates.add("vms/Controller.java.vm");
        templates.add("vms/Service.java.vm");
        templates.add("vms/ServiceImpl.java.vm");
        templates.add("vms/Dao.java.vm");

        return templates;
    }


    /**
     * 生成代码
     */
    public static void generatorCode(Map<String, Object> data, List<String> templates, ZipOutputStream zip) {

        //设置velocity资源加载器
        Properties prop = new Properties();
        prop.put("file.resource.loader.class", "org.apache.velocity.runtime.resource.loader.ClasspathResourceLoader");
        Velocity.init(prop);

        //封装模板数据
        VelocityContext context = new VelocityContext(data);

        //获取模板列表
        for (String template : templates) {
            //渲染模板
            StringWriter sw = new StringWriter();
            Template tpl = Velocity.getTemplate(template, "UTF-8");
            tpl.merge(context, sw);

            try {
                //添加到zip
                zip.putNextEntry(new ZipEntry(getFileName(template, data.get("className").toString(), data.get("package").toString())));
                IOUtils.write(sw.toString(), zip, "UTF-8");
                IOUtils.closeQuietly(sw);
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }



    /**
     * 获取文件名 , 每个文件所在包都不一样, 在磁盘上的文件名几路径也各不相同
     */
    public static String getFileName(String template, String className,String packageName) {
        String packagePath = "main" + File.separator + "java" + File.separator;
        if (StringUtils.isNotBlank(packageName)) {
            packagePath += packageName.replace(".", File.separator) + File.separator;
        }

        if (template.contains("Dao.java.vm")) {
            return packagePath + "dao" + File.separator + className + "Dao.java";
        }

        if (template.contains("Service.java.vm")) {
            return packagePath + "service" + File.separator + className + "Service.java";
        }

        if (template.contains("ServiceImpl.java.vm")) {
            return packagePath + "service" + File.separator + "impl" + File.separator + className + "ServiceImpl.java";
        }

        if (template.contains("Controller.java.vm")) {
            return packagePath + "controller" + File.separator + className + "Controller.java";
        }

        return null;
    }
}

3、测试

public static void main(String[] args) throws IOException {
    Map<String,Object> data = new HashMap<String,Object>();
    data.put("className","Product");
    data.put("classname","product");
    data.put("package","com.rewind");

    File file = new File("D:\\Users\\Desktop\\code.zip");
    FileOutputStream outputStream = new FileOutputStream(file);
    ZipOutputStream zip = new ZipOutputStream(outputStream);

    GenUtils.generatorCode(data,GenUtils.getTemplates(),zip);

    zip.close();
}

运行完毕之后, 可以看到输出路径下回自动生成一个压缩文件 , 解压之后将里面的代码copy到我们的项目之中即可 !

五、进阶-VelocityTools

Velocity Tools 是 Velocity模板引擎的一个子项目,用于将 Velocity 与 Web开发环境集成的工具包。

VelocityTools 项目分为两个部分:GenericToolsVelocityView .

  • GenericTools : GenericTools是一组类,它们提供在标准Velocity项目中使用工具的基本基础结构,以及在通用Velocity模板中使用的一组工具。例如 : DateTool、NumberTool和RenderTool很多其他可用的工具
  • Velocity view : 包括所有的通用工具结构和在web应用程序的视图层中使用Velocity的专用工具。这包括用于处理Velocity模板请求的VelocityViewServletVelocityLayoutServlet、用于在JSP中嵌入Velocity的VelocityViewTag和用于在Velocity模板中嵌入JSP标记库的Maven插件。这里流行的工具是LinkTool和ParameterTool。

六、GenericTools

GenericTools : GenericTools是一组类,它们提供在标准Velocity项目中使用工具的基本基础结构,以及在通用Velocity模板中使用的一组工具。

简单来说, GenericTools就是Velocity官方提供的一组可以在模板中使用的工具类库

1、示例代码

(1)依赖

<dependency>
    <groupId>org.apache.velocity</groupId>
    <artifactId>velocity-engine-core</artifactId>
    <version>2.2</version>
</dependency>
<dependency>
    <groupId>org.apache.velocity.tools</groupId>
    <artifactId>velocity-tools-generic</artifactId>
    <version>3.0</version>
</dependency>

(2)模板

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
当前时间 : $date.get('yyyy-MM-dd HH:mm:ss')
</body>
</html>

(3)配置

在 resource 下创建文件 configuration.xml

<?xml version="1.0" encoding="UTF-8"?>
<tools>
    <toolbox scope="application">
        <tool class="org.apache.velocity.tools.generic.DateTool"></tool>
    </toolbox>
</tools>

(4)代码

@Test
public void test1() throws IOException {
    // 创建引擎
    VelocityEngine ve = new VelocityEngine();
    // 设置模板加载路径,这里设置的是class下
    ve.setProperty(Velocity.RESOURCE_LOADER, "class");
    ve.setProperty("class.resource.loader.class", "org.apache.velocity.runtime.resource.loader.ClasspathResourceLoader");
    // 进行初始化操作
    ve.init();

    // 加载toolbox
    ToolManager manager = new ToolManager();
    manager.configure("configuration.xml");

    // 加载模板,设定模板编码
    Template tpl = ve.getTemplate("vms/demo1.vm", "UTF-8");

    // 设置初始化数据
    Context context = manager.createContext();
    context.put("now", new Date());

    FileWriter fw  = new FileWriter("D:\\work\\workspace\\velocity\\velocity_tools_01\\src\\main\\resources\\html\\demo1.html");
    //合并数据到模板
    tpl.merge(context, fw);
    //释放资源
    fw.close();
}

2、工具类及案例

格式化工具类的主要作用就是对数据进行格式化之后输出 , 例如 : 日期格式化 , 数字格式化等 , GenericTools提供的工具类有很多 , 随着时间的推移很多工具类已经过期, 有更好更安全的替代方案, 这里我们仅仅介绍一些常用工具类

(1)DateTool

DateTool用于访问和格式化日期以及格式化Date和Calendar对象。该工具还可以用于在各种日期类型之间进行转换。

模板

年 : $date.getYear()
月: $date.getMonth()
日: $date.getDay()

当前时间 : $date.format($now)
当前时间 : $date.format("yyyy-MM-dd HH:mm:ss",$now)
当前时间 : $date.get('yyyy-MM-dd HH:mm:ss')

配置

<toolbox scope="application">
    <tool  key="date" class="org.apache.velocity.tools.generic.DateTool" format="yyyy-MM-dd"></tool>
</toolbox>

格式基本上是固定的 , <toolbox> 代表配置一个工具盒 , 里面可以配置很多个工具<tool> , 这些表情上的属性有很多

  • scope : 此工具的作用范围 , requestsessionapplication
  • key : 此工具映射到的上下文键。列入当前key是date , 那么在模板中既要使用$date来使用工具 , 从VelocityTools 2 开始,工具箱可以根据其类名自动确定工具的key。一个名为 org.com.FooTool 的工具将在模板中分配键 $foo,名为 org.com.FooBarTool 的工具为 $ fooBar ,一个名为org.com.FooBar 的工具也为$ fooBar
  • class : 指定工具类的完全限定路径
  • format : 在使用DateTool工具的时候, 指定时间日期格式化得格式

(2)NumberTool

NumberTool用于访问和格式化任意数值类型对象。该工具还可以用于检索NumberFormat实例或与各种数字类型进行相互转换。

模板

原始数据 : $myNumber
格式化 : $number.format($myNumber)
取整 : $number.integer($myNumber)

配置

<toolbox scope="application">
    <tool key="number" class="org.apache.velocity.tools.generic.NumberTool" />
</toolbox>

(3)MathTool

MathTool用于在Velocity中执行数学运算。

模板

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($math.div($num1,$num2))
向下取整 : $math.floor($math.div($num1,$num2))
四舍五入 : $math.roundTo(2,$math.div($num1,$num2))  ## 第一个参数保留的位数 , 第二个参数运算的值

配置

<toolbox scope="application">
    <tool key="math" class="org.apache.velocity.tools.generic.MathTool" />
</toolbox>

(4)DisplayTool

用于控制数据显示和隐藏 , 以及数据格式的处理

模板

## list方法用于展示数据或集合中的数据 , 默认的展示格式为 A, B and C
默认输出格式 : $display.list($list)
使用,分割输出 : $display.list($list,",")

## truncate方法用于字符串截取 , 默认截取30个长度
字符串截取, 默认30个长度 : $display.truncate("truncate方法用于字符串截取默认截取30个长度")
字符串截取, 给定20个长度 : $display.truncate("truncate方法用于字符串截取默认截取30个长度",20)
字符串截取, 给定20个长度 : $display.truncate("truncate方法用于字符串截取默认截取30个长度",20,"")

## alt方法用于判断给定的数据是否为空 , 如果为空展示第二个参数 , 如果不为空展示数据本身
不为空:$display.alt($num1,"num1不为空")
为空:$display.alt($num3,"num3为空")

配置

<toolbox scope="application">
    <tool key="display" class="org.apache.velocity.tools.generic.DisplayTool"/>
</toolbox>

(5)EscapeTool

用于对一些特殊字符进转义处理 , 例如 $ , # , & 等…

模板

$velocity
$esc.velocity($velocity)

$html
$esc.html($html)

$url
$esc.url($url)
$esc.unurl($esc.url($url))

$esc.dollar     ## $
$esc.d          ## $

$esc.hash       ## #
$esc.h          ## #

$esc.backslash  ## \
$esc.b          ## \

$esc.quote      ## "
$esc.q          ## "

$esc.singleQuote    ## '
$esc.s              ## '

$esc.exclamation    ## !
$esc.e              ## !

配置

<toolbox scope="application">
    <tool key="esc" class="org.apache.velocity.tools.generic.EscapeTool"/>
</toolbox>

(6)FieldTool

用于访问类中定义的静态常量

常量类

定义MyConstants常量类

package com.itheima.constants;

public class MyConstants {

    public static  String COUNTER_NAME = "COUNTER";
}

定义Counter常量类

public class Counter {
   public static Integer MAX_VALUE = 100 ;
   public static Integer MIN_VALUE = 100 ;
}

模板

## 访问在配置中定义的静态常量
获取MyConstants中的常量 : $field.COUNTER_NAME

## 通过一个类中的常量
获取Counter类中的量 : $field.in("com.itheima.counter.Counter").MAX_VALUE

## 传入一个对象的实例 , 通过对象的实例获取其类中定义的常量
获取日历对象中的YEAR常量 : $field.in($calender).YEAR

## 默认情况下, 当我们查找了一个类的常量之后, 这个类回保存在FieldTool工具中, 可以直接获取下一个常量
获取日历对象中的DATE常量 : $field.DATE  ## 因为之前已经获取过 , 所以可以直接获取

配置

<toolbox scope="application">
    <tool key="field"  class="org.apache.velocity.tools.generic.FieldTool" include="com.itheima.constants.MyConstants"/>
</toolbox>
  • include属性可以引入一些类, 引入之后想要获取其中的常量, 直接使用 $field.常量字段名称即可 ! 引入多个类以,分割

(7)ClassTool

ClassTool用于访问一个类的Class对象信息以及其Filed , Method , Constructor等信息 , 它的设计没有考虑到代码的反射执行,因此无法通过反射执行代码。

模板

## 获取要查看的类上的所以注解 , 只有运行时期的注解才能够获取到
注解 : $class.getAnnotations()
构造方法 :
#foreach($constructor in $class.getConstructors())
    $constructor
#end
属性 :
#foreach($f in $class.getFields())
    $f
#end
方法 :
#foreach($m in $class.getMethods())
    $m
#end
包名 : $class.getPackage()
类名 : $class.getName()

## 也可以不通过配置文件 , 自己指定一个要查找的类
包名 : $class.inspect("java.lang.String").getPackage()
类名 : $class.inspect("java.lang.String").getName()
构造方法 :
#foreach($constructor in $class.inspect("java.lang.String").getConstructors())
    $constructor
#end

配置

<toolbox scope="application">
    <tool class="org.apache.velocity.tools.generic.ClassTool" inspect="com.itheima.utils.Result" ></tool>
</toolbox>
  • inspect : 指定一个需要查找的类

(8)ContextTool

用于获取Context中保存的数据和元数据

模板

context中的所有key :
#foreach( $key in $context.keys )
    $key
#end

context中的所有value :
#foreach( $value in $context.values )
    $value
#end


context中的所有key-value :
#foreach( $key in $context.keys )
    $key = $context.get($key)
#end

配置

<toolbox scope="request">
    <tool key="context" class="org.apache.velocity.tools.generic.ContextTool"/>
</toolbox>

需要注意的是在application作用范围中没有ContextTool , 所以scope需要指定为request

(9)RenderTool

Render用于将给定的字符串当作VTL秩序

#set($list = [1,2,3] )
#set($object = '$list' )
#set($method = 'size()' )
## 将字符串当作VTL秩序
$render.eval("${object}.$method")


## 使用当前上下文递归地评估包含VTL的字符串,并将结果作为字符串返回。
#macro(say_hi)
    hello world!
#end

#set($foo = "#say_hi()")
#set($bar = "$foo" )
$render.recurse($bar)

配置

<toolbox scope="request">
    <tool key="render" class="org.apache.velocity.tools.generic.RenderTool"></tool>
</toolbox>

使用recurse递归时 ,RenderTool 默认将递归限制为20个周期,以防止无限循环

(10)SortTool

SortTool 用于对集合和数组数据进行排序 , 在排序操作期间,通过调用 compareTo() 来进行比较,但要调用 compareToIgnoreCase() 的字符串除外。将集合数据转化为合适的类型后 , 通过调用 Collections.sort()来 执行排序

简单类型排序 :
#set($strList = $sorter.sort($strs))
#foreach($str in $strList)
    $str
#end

对象类型排序 - 单个字段 :
#set($users = $sorter.sort($userList,"age:asc"))
#foreach($user in $users)
    $user.name : $user.age  :  $user.sex
#end

对象类型排序 - 多字段 :
#set($users = $sorter.sort($userList,["sex:desc","age:asc"]))
#foreach($user in $users)
    $user.name : $user.age  :  $user.sex
#end

配置

<toolbox scope="application">
    <tool key="sorter" class="org.apache.velocity.tools.generic.SortTool"/>
</toolbox>

SortTool已经被标注为过期, 建议使用下面CollectionTool的排序方法

(11)CollectionTool

CollectionTool 允许用户对集合中包含的对象公开的任意任意属性集对集合(或数组,迭代器等)进行排序,并通过拆分字符串来生成数组。

模板

简单类型排序 :
#set($strList = $collection.sort($strs))
#foreach($str in $strList)
    $str
#end

对象类型排序 - 单个字段 :
#set($users = $collection.sort($userList,"age:asc"))
#foreach($user in $users)
    $user.name : $user.age  :  $user.sex
#end

对象类型排序 - 多字段 :
#set($users = $collection.sort($userList,["sex:desc","age:asc"]))
#foreach($user in $users)
    $user.name : $user.age  :  $user.sex
#end

拆分字符串 :
#set($str="hello word , how are you !")
#foreach($s in $collection.split($str))
    $s
#end

配置

<tool key="collection" class="org.apache.velocity.tools.generic.CollectionTool" stringsDelimiter=" ">
</tool>

stringsDelimiter : 指定进行字符串分割时的分割符 , 默认是,

(12)XmlTool

XmlTool用于读取和浏览XML文件。它底层使用dom4j为遍历XML文件提供完整的XPath支持。

xml

<?xml version="1.0" encoding="UTF-8"?>
<users>
    <user id="1" name="杨过" sex="" age="18" > 喜欢看书 </user>
    <user id="2" name="小龙女" sex="" age="18" > 喜欢睡觉 </user>
    <user id="3" name="郭靖" sex="" age="18" > 喜欢玩游戏 </user>
    <user id="4" name="黄蓉" sex="" age="18" > 喜欢喝酒 </user>
</users>

模板

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>

$xml.find("//user[@id='1']")
$xml.find("//user[@id='1']").attr("name")
$xml.find("//user[@id='1']").text


</body>
</html>

配置

<toolbox scope="application">
    <tool key="xml" class="org.apache.velocity.tools.generic.XmlTool"  resource="xml/user.xml"/>
</toolbox>

resource : 加载类路径下的XML资源

source : 加载一个URL路径下的XML资源

七、VelocityView

VelocityView 包含所有 GenericTools 并添加了用于在Web应用程序(Java EE项目)的视图层中使用Velocity的基础结构和专用工具。这包括用于处理Velocity模板请求的VelocityViewServletVelocityLayoutServlet,以及用于将Velocity嵌入JSP中的VelocityViewTag

1、使用步骤

(1)依赖

<dependency>
    <groupId>org.apache.velocity</groupId>
    <artifactId>velocity-engine-core</artifactId>
    <version>2.2</version>
</dependency>
<dependency>
    <groupId>org.apache.velocity.tools</groupId>
    <artifactId>velocity-tools-view</artifactId>
    <version>3.0</version>
</dependency>

  目录