Apache Velocity Tools 3.1 快速入门与集成示例

Apache Velocity Tools 3.1 快速入门:从 Maven 工程依赖集成到 tools.xml 工具箱声明、ToolManager 加载与模板渲染,再到无 Maven 服务器手动 jar 集成,逐步附真实编译运行回显,可照抄复现。

Apache VelocityApache Velocity2026/10/15

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
JDKOpenJDK 17.0.20.1(Temurin 发行版);手动集成环境为发行版 OpenJDK 17.0.20.1+1-1-22.04-Ubuntu
Maven3.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 实测。

二、前置条件

  1. 主环境已安装 JDK 17 与 Maven 3.9.x,mvn -v 可正常回显;第五节的手动集成环境只需 JDK 17 与 curl。
  2. 服务器可访问仓库 repo1.maven.org。
  3. 会话 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);
    }
}

两个关键点:

  1. new ToolManager() 默认不加载任何工具箱,必须显式调用 manager.configure("tools.xml")。
  2. 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 转义:&lt;b&gt;hello &amp; welcome&lt;/b&gt;
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 转义:&lt;b&gt;hello &amp; welcome&lt;/b&gt;
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 直跑,结果稳定。

七、参考资料

  1. Velocity Tools 3.1 用户指南:https://velocity.apache.org/tools/3.1/
  2. Maven Central 构件页:https://central.sonatype.com/artifact/org.apache.velocity.tools/velocity-tools-generic/3.1
  3. 专栏前置文档:《Apache Velocity 快速入门与集成示例》《Apache Velocity 配置参数详解》。
  4. 下一篇专题文档:《Apache Velocity Tools 3.1 通用工具与工具箱配置详解》。