Apache Velocity Tools 3.1 快速入门与集成示例
Apache Velocity Tools 3.1 快速入门:从 Maven 工程依赖集成到 tools.xml 工具箱声明、ToolManager 加载与模板渲染,再到无 Maven 服务器手动 jar 集成,逐步附真实编译运行回显,可照抄复现。
Apache Velocity Tools 3.1 快速入门与集成示例
目标:在 Maven 工程与无 Maven 服务器两种环境完成 velocity-tools-generic 3.1 集成,用 ToolManager 加载 tools.xml 工具箱并渲染模板,全部命令与回显实测通过。
一、环境信息
| 项目 | 值 |
|---|---|
| 主环境操作系统 | Ubuntu 24.04.5 LTS |
| 手动集成环境操作系统 | Ubuntu 22.04.5 LTS |
| 登录账号 | root |
| JDK | OpenJDK 17.0.20.1(Temurin 发行版);手动集成环境为发行版 OpenJDK 17.0.20.1+1-1-22.04-Ubuntu |
| Maven | 3.9.16 |
| 模板引擎 | velocity-engine-core 2.4.1 |
| 工具箱 | velocity-tools-generic 3.1 |
| 日志绑定 | slf4j-simple 1.7.36 |
| 工程目录 | /root/velocity-tools-demo(Maven)、/root/velocity-tools-standalone(手动) |
版本说明:Maven Central 元数据显示 org.apache.velocity.tools 组下的 velocity-tools-generic 与 velocity-tools-view 在 3.x 系列只有 3.0 与 3.1 两个版本,latest 与 release 均为 3.1,元数据最后更新时间为 2021-03-07,本文按 3.1 实测。
二、前置条件
- 主环境已安装 JDK 17 与 Maven 3.9.x,
mvn -v可正常回显;第五节的手动集成环境只需 JDK 17 与 curl。 - 服务器可访问仓库 repo1.maven.org。
- 会话 locale 为 UTF-8(最小环境执行
export LANG=C.UTF-8,否则模板中文乱码)。
三、Maven 工程集成
3.1 创建工程结构
mkdir -p /root/velocity-tools-demo/src/main/java/com/example
mkdir -p /root/velocity-tools-demo/src/main/resources/templates
本文不用 archetype,目录手工创建,全程只需 4 个文件:pom.xml、tools.xml、ToolsDemo.java、tools-demo.vm。
3.2 pom.xml
/root/velocity-tools-demo/pom.xml:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.example</groupId>
<artifactId>velocity-tools-demo</artifactId>
<version>1.0.0</version>
<packaging>jar</packaging>
<properties>
<maven.compiler.source>17</maven.compiler.source>
<maven.compiler.target>17</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<dependency>
<groupId>org.apache.velocity</groupId>
<artifactId>velocity-engine-core</artifactId>
<version>2.4.1</version>
</dependency>
<dependency>
<groupId>org.apache.velocity.tools</groupId>
<artifactId>velocity-tools-generic</artifactId>
<version>3.1</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-simple</artifactId>
<version>1.7.36</version>
</dependency>
</dependencies>
</project>
💡 技术拓展:velocity-tools-generic 3.1 会传递引入 commons-beanutils 1.9.4、commons-digester3 3.2、commons-lang3 3.17.0、commons-logging 1.2、json-simple 3.0.2、slf4j-api 1.7.36;JsonTool 底层用 json-simple,XmlTool 用 JDK 内置的 org.w3c.dom,都不需要额外加依赖。不要用旧坐标 org.apache.velocity:velocity-tools:2.0,那是面向 Velocity 1.7 的旧包。
3.3 构建并落盘依赖
cd /root/velocity-tools-demo && mvn package && mvn -q dependency:copy-dependencies -DoutputDirectory=libs
实测回显(节选):
[INFO] Building velocity-tools-demo 1.0.0
[INFO] Building jar: /root/velocity-tools-demo/target/velocity-tools-demo-1.0.0.jar
[INFO] BUILD SUCCESS
[INFO] Total time: 2.037 s
ls -l libs 实测输出:
total 2592
-rw-r--r-- 1 root root 246918 Jul 28 2019 commons-beanutils-1.9.4.jar
-rw-r--r-- 1 root root 588337 Nov 12 2015 commons-collections-3.2.2.jar
-rw-r--r-- 1 root root 241614 Dec 10 2011 commons-digester3-3.2.jar
-rw-r--r-- 1 root root 673587 Aug 24 2024 commons-lang3-3.17.0.jar
-rw-r--r-- 1 root root 61829 Jul 5 2014 commons-logging-1.2.jar
-rw-r--r-- 1 root root 35059 Jan 24 2018 json-simple-3.0.2.jar
-rw-r--r-- 1 root root 41125 Feb 8 2022 slf4j-api-1.7.36.jar
-rw-r--r-- 1 root root 15333 Feb 8 2022 slf4j-simple-1.7.36.jar
-rw-r--r-- 1 root root 515658 Oct 14 2024 velocity-engine-core-2.4.1.jar
-rw-r--r-- 1 root root 216933 Feb 27 2021 velocity-tools-generic-3.1.jar
💡 技术拓展:依赖落盘后用
java -cp 'target/classes:libs/*'直跑,比 exec:java 插件更稳。实测同一工程 exec:java 偶发插件类加载异常(报缺 org.apache.velocity.util.StringUtils),直跑方式每次结果一致。
四、tools.xml 工具箱与 ToolManager 渲染
4.1 声明工具箱 tools.xml
/src/main/resources/tools.xml:
<?xml version="1.0" encoding="UTF-8"?>
<tools>
<toolbox scope="application">
<tool class="org.apache.velocity.tools.generic.DateTool" key="date"/>
<tool class="org.apache.velocity.tools.generic.MathTool" key="math"/>
<tool class="org.apache.velocity.tools.generic.NumberTool" key="number"/>
<tool class="org.apache.velocity.tools.generic.DisplayTool" key="display"/>
<tool class="org.apache.velocity.tools.generic.EscapeTool" key="esc"/>
<tool class="org.apache.velocity.tools.generic.SortTool" key="sorter"/>
<tool class="org.apache.velocity.tools.generic.ComparisonDateTool" key="compdate"/>
<tool class="org.apache.velocity.tools.generic.FieldTool" key="field"/>
<tool class="org.apache.velocity.tools.generic.ClassTool" key="class"/>
</toolbox>
<toolbox scope="request">
<tool class="org.apache.velocity.tools.generic.LoopTool" key="loop"/>
<tool class="org.apache.velocity.tools.generic.JsonTool" key="json"/>
<tool class="org.apache.velocity.tools.generic.XmlTool" key="xml"/>
<tool class="org.apache.velocity.tools.generic.LinkTool" key="link"/>
</toolbox>
</tools>
作用域规则:application 工具箱中的工具是跨模板共享的单例;request 工具箱中的工具每次渲染新建实例。LoopTool、JsonTool、XmlTool、LinkTool 的默认作用域是 request,放进 application 工具箱会在 configure 阶段直接抛异常,实测回显:
configure FAILED: org.apache.velocity.tools.config.InvalidScopeException: Toolbox with scope 'application' may not contain a org.apache.velocity.tools.generic.LoopTool.
💡 技术拓展:application 适合无状态工具(MathTool、EscapeTool 等),request 适合有游标或请求上下文的工具(LoopTool 的迭代游标、LinkTool 的当前链接状态)。拿不准时看该工具类的默认作用域,第五篇专题文档给出全部工具的默认作用域分组表。
4.2 主类 ToolsDemo.java
/src/main/java/com/example/ToolsDemo.java:
package com.example;
import org.apache.velocity.Template;
import org.apache.velocity.app.VelocityEngine;
import org.apache.velocity.context.Context;
import org.apache.velocity.tools.ToolManager;
import java.io.StringWriter;
import java.util.Date;
import java.util.List;
public class ToolsDemo {
public static void main(String[] args) {
VelocityEngine engine = new VelocityEngine();
engine.setProperty("resource.loaders", "classpath");
engine.setProperty("resource.loader.classpath.class",
"org.apache.velocity.runtime.resource.loader.ClasspathResourceLoader");
engine.setProperty("resource.default_encoding", "UTF-8");
engine.init();
ToolManager manager = new ToolManager();
manager.configure("tools.xml");
Context context = manager.createContext();
context.put("now", new Date());
context.put("nums", List.of(5, 3, 9, 1, 7));
context.put("title", "Apache Velocity Tools Generic 工具箱");
Template template = engine.getTemplate("templates/tools-demo.vm", "UTF-8");
StringWriter writer = new StringWriter();
template.merge(context, writer);
System.out.println("========== tools.xml 工具箱渲染结果 ==========");
System.out.println(writer);
}
}
两个关键点:
new ToolManager()默认不加载任何工具箱,必须显式调用manager.configure("tools.xml")。- configure 的参数按 classpath 与文件系统两条路径查找,本文的 tools.xml 位于 classpath 根(target/classes 下)。
4.3 模板 tools-demo.vm
/src/main/resources/templates/tools-demo.vm:
日期格式化:$date.format('yyyy-MM-dd HH:mm:ss', $now)
数学运算:$math.add(19, 23) / $math.mul(6, 7)
数字格式化:$number.integer(1234567.891) / $number.percent(0.2568)
标题截断:$display.truncate($title, 18)
HTML 转义:$esc.html('<b>hello & welcome</b>')
URL 编码:$esc.url('quzuo net')
循环计数:#foreach( $i in $loop.watch($nums) )$loop.count=$i #end
4.4 编译运行
cd /root/velocity-tools-demo && mvn -q package && java -cp 'target/classes:libs/*' com.example.ToolsDemo
实测回显:
========== tools.xml 工具箱渲染结果 ==========
日期格式化:2026-10-15 13:07:30
数学运算:42 / 42
数字格式化:1,234,568 / 26%
标题截断:Apache Velocity...
HTML 转义:<b>hello & welcome</b>
URL 编码:quzuo+net
循环计数:1=5 2=3 3=9 4=1 5=7
五、无 Maven 环境手动集成
5.1 安装 JDK 17 与 curl
apt-get install -y openjdk-17-jdk-headless curl
java -version 实测回显:
openjdk version "17.0.20.1" 2026-08-18
OpenJDK Runtime Environment (build 17.0.20.1+1-1-22.04-Ubuntu)
OpenJDK 64-Bit Server VM (build 17.0.20.1+1-1-22.04-Ubuntu, mixed mode, sharing)
5.2 下载依赖 jar
mkdir -p /root/velocity-tools-standalone/libs
mkdir -p /root/velocity-tools-standalone/classes
mkdir -p /root/velocity-tools-standalone/src/main/java/com/example
mkdir -p /root/velocity-tools-standalone/src/main/resources/templates
cd /root/velocity-tools-standalone/libs
curl -fsSLO https://repo1.maven.org/maven2/org/apache/velocity/velocity-engine-core/2.4.1/velocity-engine-core-2.4.1.jar
curl -fsSLO https://repo1.maven.org/maven2/org/apache/velocity/tools/velocity-tools-generic/3.1/velocity-tools-generic-3.1.jar
curl -fsSLO https://repo1.maven.org/maven2/org/slf4j/slf4j-api/1.7.36/slf4j-api-1.7.36.jar
curl -fsSLO https://repo1.maven.org/maven2/org/slf4j/slf4j-simple/1.7.36/slf4j-simple-1.7.36.jar
curl -fsSLO https://repo1.maven.org/maven2/commons-beanutils/commons-beanutils/1.9.4/commons-beanutils-1.9.4.jar
curl -fsSLO https://repo1.maven.org/maven2/org/apache/commons/commons-digester3/3.2/commons-digester3-3.2.jar
curl -fsSLO https://repo1.maven.org/maven2/org/apache/commons/commons-lang3/3.17.0/commons-lang3-3.17.0.jar
curl -fsSLO https://repo1.maven.org/maven2/commons-collections/commons-collections/3.2.2/commons-collections-3.2.2.jar
curl -fsSLO https://repo1.maven.org/maven2/commons-logging/commons-logging/1.2/commons-logging-1.2.jar
ls -l 实测输出:
total 2556
-rw-r--r-- 1 root root 246918 Oct 15 13:03 commons-beanutils-1.9.4.jar
-rw-r--r-- 1 root root 588337 Oct 15 13:03 commons-collections-3.2.2.jar
-rw-r--r-- 1 root root 241614 Oct 15 13:03 commons-digester3-3.2.jar
-rw-r--r-- 1 root root 673587 Oct 15 13:03 commons-lang3-3.17.0.jar
-rw-r--r-- 1 root root 61829 Oct 15 13:03 commons-logging-1.2.jar
-rw-r--r-- 1 root root 41125 Oct 15 13:03 slf4j-api-1.7.36.jar
-rw-r--r-- 1 root root 15333 Oct 15 13:03 slf4j-simple-1.7.36.jar
-rw-r--r-- 1 root root 515658 Oct 15 13:03 velocity-engine-core-2.4.1.jar
-rw-r--r-- 1 root root 216933 Oct 15 13:03 velocity-tools-generic-3.1.jar
各 jar 用途:velocity-engine-core 与 velocity-tools-generic 是主件;slf4j-api 加 slf4j-simple 负责日志;commons-beanutils、commons-digester3、commons-lang3、commons-collections、commons-logging 是工具箱配置解析与工具实现依赖。若不用 JsonTool,json-simple(3.1 传递依赖,此处未单独下载也可由 generic 依赖链带入 Maven 工程)可忽略。
5.3 编译与运行
源码文件与第四节完全一致(ToolsDemo.java、tools.xml、tools-demo.vm),按相同目录结构放到 src/main 下,然后:
cd /root/velocity-tools-standalone
javac -encoding UTF-8 -cp 'libs/*' -d classes src/main/java/com/example/ToolsDemo.java
cp src/main/resources/tools.xml classes/
mkdir -p classes/templates
cp src/main/resources/templates/tools-demo.vm classes/templates/
java -cp 'classes:libs/*' com.example.ToolsDemo
实测回显(与 Maven 工程输出一致,仅时间戳不同):
========== tools.xml 工具箱渲染结果 ==========
日期格式化:2026-10-15 13:05:40
数学运算:42 / 42
数字格式化:1,234,568 / 26%
标题截断:Apache Velocity...
HTML 转义:<b>hello & welcome</b>
URL 编码:quzuo+net
循环计数:1=5 2=3 3=9 4=1 5=7
六、常见问题
Q1:模板里 $date、$math 原样输出是什么原因?
按顺序排查三点:一是 new ToolManager() 后没有调用 configure("tools.xml")(默认不加载任何工具);二是 tools.xml 不在 classpath 根;三是工具类被放错作用域,configure 阶段已抛 InvalidScopeException,看启动日志即可定位。
Q2:request 作用域工具误放进 application 工具箱会怎样? configure 阶段直接抛 InvalidScopeException,整个工具箱加载失败,本文 4.1 节有实测回显。
Q3:exec:java 报 A required class was missing ... org/apache/velocity.util.StringUtils 怎么办? 实测这是 exec 插件类加载策略在个别环境的偶发问题,与工程代码无关;改用 3.3 节的 dependency:copy-dependencies 加 java -cp 直跑,结果稳定。
七、参考资料
- Velocity Tools 3.1 用户指南:https://velocity.apache.org/tools/3.1/
- Maven Central 构件页:https://central.sonatype.com/artifact/org.apache.velocity.tools/velocity-tools-generic/3.1
- 专栏前置文档:《Apache Velocity 快速入门与集成示例》《Apache Velocity 配置参数详解》。
- 下一篇专题文档:《Apache Velocity Tools 3.1 通用工具与工具箱配置详解》。