Velocity案例

wen java案例 2

本文目录导读:

Velocity案例

  1. 什么是 Velocity?
  2. 一个完整的实战案例:生成用户报表
  3. Velocity 语法核心点总结
  4. 常见问题与优化建议

什么是 Velocity?

Velocity 是一个基于 Java 的模板引擎,它允许你使用简单的模板语言(VTL - Velocity Template Language)来引用 Java 代码中定义的对象和方法,它的核心理念是将前端页面与后端逻辑分离,前端开发者专注于编写页面结构,后端开发者提供数据模型。

主要用途:

  • 生成 Web 页面(类似 JSP,但更轻量)
  • 生成 SQL、XML、邮件内容等文本
  • 代码生成器(如 MyBatis 逆向工程)

一个完整的实战案例:生成用户报表

在这个案例中,我们将使用 Velocity 从一个用户数据列表生成一个 HTML 报表。

环境准备(Maven 依赖)

在你的 pom.xml 中添加 Velocity 的依赖:

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

创建 Velocity 模板文件 (user_report.vm)

src/main/resources/templates 目录下创建该文件。

<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">用户报表 - ${reportTitle}</title>
    <style>
        table {
            border-collapse: collapse;
            width: 100%;
        }
        th, td {
            border: 1px solid #ddd;
            padding: 8px;
            text-align: left;
        }
        tr:nth-child(even) {
            background-color: #f2f2f2;
        }
        th {
            background-color: #4CAF50;
            color: white;
        }
    </style>
</head>
<body>
    <h1>${reportTitle}</h1>
    <p>生成日期:${generatedDate}</p>
    #if($users.isEmpty())
        <p><strong>暂无用户数据。</strong></p>
    #else
        <table>
            <tr>
                <th>用户ID</th>
                <th>姓名</th>
                <th>邮箱</th>
                <th>状态</th>
            </tr>
            #foreach($user in $users)
            <tr>
                <td>$!{user.id}</td>  <!-- $! 表示如果为 null 则输出空字符串 -->
                <td>$!{user.name}</td>
                <td>
                    #if($user.email)
                        <a href="mailto:${user.email}">$user.email</a>
                    #else
                        <span style="color: gray;">未填写</span>
                    #end
                </td>
                <td>
                    #if($user.status == "ACTIVE")
                        <span style="color: green;">活跃</span>
                    #elseif($user.status == "DISABLED")
                        <span style="color: red;">禁用</span>
                    #else
                        <span style="color: orange;">未知</span>
                    #end
                </td>
            </tr>
            #end
        </table>
        <p>总用户数:${users.size()}</p>
    #end
</body>
</html>

创建用户模型类 (User.java)

这是一个简单的 POJO 类。

public class User {
    private Long id;
    private String name;
    private String email;
    private String status; // ACTIVE, DISABLED
    // 构造函数、getter/setter 省略,但必须齐全
    public User() {}
    public User(Long id, String name, String email, String status) {
        this.id = id;
        this.name = name;
        this.email = email;
        this.status = status;
    }
    public Long getId() { return id; }
    public void setId(Long id) { this.id = id; }
    public String getName() { return name; }
    public void setName(String name) { this.name = name; }
    public String getEmail() { return email; }
    public void setEmail(String email) { this.email = email; }
    public String getStatus() { return status; }
    public void setStatus(String status) { this.status = status; }
}

Java 主程序 (VelocityReportGenerator.java)

这是核心的调用代码。

import org.apache.velocity.Template;
import org.apache.velocity.VelocityContext;
import org.apache.velocity.app.VelocityEngine;
import org.apache.velocity.runtime.RuntimeConstants;
import org.apache.velocity.runtime.resource.loader.ClasspathResourceLoader;
import java.io.StringWriter;
import java.nio.charset.StandardCharsets;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
public class VelocityReportGenerator {
    public static void main(String[] args) {
        // 1. 初始化 Velocity 引擎
        VelocityEngine velocityEngine = new VelocityEngine();
        // 设置模板资源加载器为 Classpath(即读取 resources 下的文件)
        velocityEngine.setProperty(RuntimeConstants.RESOURCE_LOADER, "classpath");
        velocityEngine.setProperty("classpath.resource.loader.class", ClasspathResourceLoader.class.getName());
        // 设置编码,防止中文乱码
        velocityEngine.setProperty(RuntimeConstants.INPUT_ENCODING, "UTF-8");
        velocityEngine.setProperty(RuntimeConstants.OUTPUT_ENCODING, "UTF-8");
        velocityEngine.init();
        // 2. 创建上下文(数据模型),并填充数据
        VelocityContext context = new VelocityContext();
        context.put("reportTitle", "2024年第一季度用户统计报告");
        context.put("generatedDate", new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
        // 创建模拟的用户数据
        List<User> users = new ArrayList<>();
        users.add(new User(1L, "张三", "zhangsan@example.com", "ACTIVE"));
        users.add(new User(2L, "李四", null, "DISABLED")); // 没有邮箱
        users.add(new User(3L, "王五", "wangwu@example.com", "ACTIVE"));
        users.add(new User(4L, "赵六", "zhaoliu@example.com", "PENDING"));
        context.put("users", users);
        // 3. 获取模板
        Template template = velocityEngine.getTemplate("templates/user_report.vm", "UTF-8");
        // 4. 合并模板和数据(渲染)
        StringWriter writer = new StringWriter();
        template.merge(context, writer);
        // 5. 输出结果
        System.out.println("========== 生成的 HTML 内容 ==========");
        System.out.println(writer);
        // 你可以将 writer.toString() 保存到文件或通过 HTTP 响应输出
    }
}

运行结果

运行 main 方法后,控制台将输出完整的 HTML 代码,它的关键渲染部分如下:

<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">用户报表 - 2024年第一季度用户统计报告</title>
    <!-- 样式省略 -->
</head>
<body>
    <h1>2024年第一季度用户统计报告</h1>
    <p>生成日期:2024-05-20 10:30:45</p>
    <!-- 表格部分 -->
    <table>
        <tr>
            <th>用户ID</th>
            <th>姓名</th>
            <th>邮箱</th>
            <th>状态</th>
        </tr>
        <tr>
            <td>1</td>
            <td>张三</td>
            <td><a href="mailto:zhangsan@example.com">zhangsan@example.com</a></td>
            <td><span style="color: green;">活跃</span></td>
        </tr>
        <tr>
            <td>2</td>
            <td>李四</td>
            <td><span style="color: gray;">未填写</span></td>
            <td><span style="color: red;">禁用</span></td>
        </tr>
        <!-- 王五、赵六等 -->
        <p>总用户数:4</p>
    </table>
</body>
</html>

Velocity 语法核心点总结

了解以下语法,你就可以应对大部分场景:

  1. 引用变量$variable${variable}(更推荐后者,可避免拼接歧义)。
  2. 空值安全引用$!{variable},如果变量为 null,则输出空字符串而不是 "$variable"
  3. 设置属性#set($var = "value")
  4. 条件判断#if / #elseif / #else / #end
  5. 循环遍历#foreach($item in $collection) / #end,可以使用 $foreach.index(索引)和 $foreach.hasNext
  6. 引入其他模板#parse("header.vm")#include("footer.html")
  7. 注释## This is a comment(单行)和 (多行)。
  8. 调用方法:可以直接调用对象的 getter 方法(如 $user.getName() 通常简写为 $user.name),也可以在模板中调用带参数的方法(如 $user.isActive())。

常见问题与优化建议

  • 中文乱码:务必在初始化引擎时设置 input.encodingoutput.encodingUTF-8,并在获取模板时指定编码(如 getTemplate(path, "UTF-8"))。
  • 性能:如果你的应用是高并发场景(如 Web MVC),建议使用 VelocityEngine 的单例实例,并在应用启动时预加载模板,而不是每次请求都创建新引擎。
  • 不要在模板中写复杂业务逻辑:Velocity 的职责是展示数据,复杂的判断和计算应放在 Java 后台完成,只把最终结果放入上下文,保持模板简洁。

如果你需要处理更复杂的场景(如宏定义、布局装饰等),Velocity 还提供了 #macro 和布局工具,可以进一步探索,希望这个例子能帮你顺利上手!如果你还有其他 Velocity 相关的问题,欢迎继续提问。

抱歉,评论功能暂时关闭!