Thymeleaf模板引擎实战:从基础语法到PDF生成与Spring Boot集成

1. 为什么今天还在聊Thymeleaf?

如果你是一个Java Web开发者,尤其是使用Spring Boot的,那么“Thymeleaf”这个名字你一定不陌生。但你可能也听过这样的声音:“现在都前后端分离了,谁还用模板引擎啊?” 或者 “Vue/React不香吗,为什么还要学这个?” 作为一个从JSP时代一路走过来的老码农,我想说,Thymeleaf不仅没有过时,反而在特定的场景下,它依然是那个最优雅、最省心的解决方案。今天,我们就抛开那些“非此即彼”的争论,深入聊聊Thymeleaf到底是什么,它解决了哪些实际问题,以及如何把它用得“飞起”。

简单来说,Thymeleaf是一个现代化的、服务于Web和独立环境的Java模板引擎。它的核心卖点是“自然模板”——模板文件本身就是有效的HTML5,可以直接在浏览器里打开预览,然后通过Thymeleaf的属性(如 th:text )在服务器端动态渲染内容。这听起来可能有点抽象,但它的好处是实实在在的:前端设计师和后端开发者可以基于同一份HTML文件协作,无需为了预览效果而启动一个笨重的服务器,极大地提升了开发效率和体验。

那么,哪些场景下Thymeleaf依然是首选呢?首先, 快速原型和内部管理系统 。当你需要快速搭建一个功能完整、带表单、列表、分页的后台管理界面时,用Thymeleaf配合Spring Boot,可能比折腾一套前后端分离的架子要快上好几倍。其次, 服务端渲染的邮件模板、报表导出 。比如,你需要生成一份样式复杂的PDF合同或带图表的数据报告,Thymeleaf结合像 Flying Saucer 这样的PDF渲染库,简直是天作之合。最后,对于 SEO有强需求的、内容为主的网站 ,服务端渲染(SSR)依然是保证内容第一时间被搜索引擎抓取的最佳实践,Thymeleaf在这里扮演着关键角色。

所以,无论你是刚入门Java Web的新手,想找一个直观易懂的视图层技术;还是经验丰富的老手,在寻找一个可靠的报表生成或邮件模板方案,Thymeleaf都值得你花时间深入了解。接下来,我会带你从零开始,不仅学会它的基本语法,更会深入到布局、PDF生成、分页等高级实战技巧,这些都是我踩过无数坑后总结出来的干货。

2. 环境搭建与第一个“Hello Thymeleaf”

理论说再多,不如动手跑一遍。我们以最流行的Spring Boot 3.x为例,搭建一个最简单的Thymeleaf项目。这里我假设你已经有基本的Spring Boot和Maven/Gradle知识。

2.1 项目初始化与依赖引入

首先,通过 Spring Initializr 创建一个新项目,选择:

  • Project : Maven
  • Language : Java
  • Spring Boot : 3.2.x (最新稳定版)
  • Dependencies : 添加 Spring Web Thymeleaf

生成的 pom.xml 中,关键的依赖是这样的:

<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-thymeleaf</artifactId>
    </dependency>
    <!-- 其他依赖... -->
</dependencies>

注意 :Spring Boot 3.x 默认集成的Thymeleaf版本是3.1.x,这是一个非常成熟稳定的版本。如果你需要用到一些新特性,可以手动指定版本,但通常不建议,以免出现兼容性问题。

2.2 理解默认约定与目录结构

Spring Boot为Thymeleaf提供了“约定大于配置”的极致体验。默认情况下,你不需要任何配置。模板文件应该放在 src/main/resources/templates/ 目录下,这是Thymeleaf的默认模板解析路径。静态资源(CSS, JS, 图片)则放在 src/main/resources/static/ 目录下。

让我们创建一个简单的控制器 HelloController.java

package com.example.demo.controller;

import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;

@Controller // 注意是@Controller,不是@RestController
public class HelloController {

    @GetMapping("/hello")
    public String sayHello(Model model) {
        model.addAttribute("message", "Hello, Thymeleaf!");
        model.addAttribute("currentTime", java.time.LocalDateTime.now());
        return "hello"; // 这对应 templates/hello.html
    }
}

关键点解析:

  1. @Controller :这个注解表明这个类是一个Web控制器,它的方法返回值通常对应一个视图(HTML页面)的名称。
  2. Model 参数 :这是一个键值对容器,用于在控制器和视图之间传递数据。我们通过 model.addAttribute(key, value) 放入数据。
  3. 返回值 "hello" :这个字符串会被Thymeleaf的 TemplateResolver 解析,自动去寻找 templates/hello.html 文件。

2.3 创建第一个模板:hello.html

现在,在 src/main/resources/templates/ 下创建 hello.html

<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <title>Thymeleaf入门</title>
</head>
<body>
    <h1 th:text="${message}">这里的内容会被替换</h1>
    <p>当前时间是:<span th:text="${currentTime}">2023-01-01T00:00:00</span></p>
    <p>这是一个静态段落,不会被Thymeleaf处理。</p>

    <hr>
    <h2>体验“自然模板”</h2>
    <p>你现在可以直接在浏览器中打开这个HTML文件(不通过服务器),你会看到“这里的内容会被替换”和“2023-01-01T00:00:00”这些静态文本。这就是设计稿。</p>
    <p>当你通过 <a href="/https://localhost:8080/hello" target="_blank">http://localhost:8080/hello</a> 访问时,Thymeleaf引擎会动态地将 <code>th:text</code> 属性中的表达式求值,并替换标签体的内容。</p>
</body>
</html>

核心语法解析:

  • xmlns:th="http://www.thymeleaf.org" :在 <html> 标签中引入Thymeleaf的命名空间。这是必须的,它告诉浏览器和编辑器,以 th: 开头的属性是Thymeleaf的指令。
  • th:text="${expression}" :这是最常用的属性之一。 ${...} 是变量表达式,用于获取上下文中的变量值。 th:text 会计算表达式的值,并将其设置为该HTML元素的文本内容,同时会转义HTML特殊字符(如 < , > ),防止XSS攻击。
  • 静态后备内容 :在 h1 span 标签体内,我们写了“这里的内容会被替换”和“2023-01-01T00:00:00”。这些内容在直接预览时显示,在服务器渲染时被替换。这是“自然模板”的精髓。

启动你的Spring Boot应用,访问 http://localhost:8080/hello ,你会看到动态渲染的页面。而直接用浏览器打开 hello.html 文件,看到的是静态原型。这种无缝切换,正是Thymeleaf提升协作效率的秘密。

3. Thymeleaf核心语法与表达式深度解析

掌握了基本用法后,我们来系统学习Thymeleaf的语法体系。它的强大,很大程度上源于其丰富而灵活的表达式。

3.1 四大核心表达式

Thymeleaf主要有四种表达式,用于在模板的不同位置插入动态内容。

  1. 变量表达式 ${...} 这是最常用的表达式,用于访问容器(Model、Session等)中的变量。它支持OGNL(Object-Graph Navigation Language)和Spring EL(Spring Expression Language),因此功能非常强大。

    <p>用户名:<span th:text="${user.name}">张三</span></p>
    <p>年龄:<span th:text="${user.age}">25</span></p>
    <!-- 支持方法调用 -->
    <p>姓名大写:<span th:text="${user.name.toUpperCase()}">ZHANGSAN</span></p>
    <!-- 支持条件判断(三元运算符) -->
    <p>状态:<span th:text="${user.isActive} ? '活跃' : '禁用'">活跃</span></
「LLM那些事」系列第 4 篇《上下文窗口的边界》,文章连接:https://blog.csdn.net/houwenjin/article/details/163999753。 演示什么:在「预测」Sheet 的黄色格子里输入一句话(默认「来泡一杯」),四个「模型」——分别只统计最后 1 / 2 / 3 / 4 个字的 n-gram 查表——同时预测下一个字。同一个输入,看的上下文越长,候选越少、预测越确定: ┌────────────────┬──────────┬───────────────┬──────┐ │ 只看最后几个字 │ 用的前缀 │ 候选下一字数 │ 预测 │ ├────────────────┼──────────┼───────────────┼──────┤ │ 1 个 │ 杯 │ 3(茶/子/水) │ 模糊 │ ├────────────────┼──────────┼───────────────┼──────┤ │ 2 个 │ 一杯 │ 2(茶/水) │ 收窄 │ ├────────────────┼──────────┼───────────────┼──────┤ │ 3 个 │ 泡一杯 │ 1(茶) │ 确定 │ ├────────────────┼──────────┼───────────────┼──────┤ │ 4 个 │ 来泡一杯 │ 1(茶) │ 确定 │ └────────────────┴──────────┴───────────────┴──────┘
源码下载地址: https://pan.quark.cn/s/a4b39357ea24 笔记本的散热风扇管理 ---------------------------------------- 09 November 2006. 对于版本20061109的变更概述如下: 1) ACPI CA核心子系统:在源操作数是一个操作区域的场景下,对负载ASL操作符进行了优化。仅需映射操作区域内存,而不是执行逐字节读取。 (区域必须为SystemMemory类型,见下文。)修正了源操作数为区域字段的负载ASL操作符问题。也允许缓冲区对象作为源操作数。 BZ 480 解决了负载ASL操作符允许源操作数为任意类型操作区域的问题。现被限制为仅SystemMemory类型的区域,符合ACPI规范。 BZ 481 对新表管理器代码进行了额外的清理和优化。AcpiEnable将在所有必需的ACPI表未加载时失败(FADT, FACS, DSDT)。 BZ 477 在acobject.h中添加了#pragma pack(8/4),以确保此头文件中的结构始终编译为对齐。ACPI_OPERAND_OBJECT已被手动优化为对齐,并在字节打包时无法工作。示例代码和数据大小:这些是Microsoft Visual C++ 6.0 32位编译器生成的、操作系统无关的acpica.lib的大小。调试版本的代码包含调试输出跟踪机制,具有更大的代码和数据大小。上一个版本:非调试版本:78.1K代码,17.1K数据,95.2K总计 调试版本:155.4K代码,63.1K数据,218.5K总计 当前版本:非调试版本:77.9K代码,17.0K数据,94.9K总计 调试版本:155.2K代码,63.1K数据,...
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值