Thymeleaf高级特性与工具对象详解

引言:为什么需要掌握Thymeleaf高级特性?

Thymeleaf作为一款面向Java的现代服务器端模板引擎,以其原生HTML支持、无缝集成Spring生态和强大的表达式能力,成为Spring Boot项目中视图层的首选方案。除了基础的变量渲染和标签使用外,Thymeleaf的高级特性(如模板布局、片段复用、动态表单处理)内置工具对象(如日期格式化、集合操作、字符串处理) 能显著提升开发效率,实现更优雅、可维护的模板代码。本文将深入剖析这些高级功能,结合实战示例带你从"会用"到"精通"。

一、Thymeleaf高级特性:构建灵活可复用的模板体系

1.1 模板布局与片段复用:告别重复代码

在Web开发中,页面的公共区域(如导航栏、页脚、侧边栏) 通常需要在多个页面中复用。Thymeleaf通过片段定义(th:fragment)片段引入(th:replace/th:insert/th:include) 解决这一问题,配合Layout Dialect布局方言可实现更强大的模板继承。

1.1.1 基础片段定义与引入

定义片段:使用th:fragment标记可复用的HTML片段,通常放在fragments目录下(如fragments/header.html):

<!-- src/main/resources/templates/fragments/header.html -->
<header th:fragment="siteHeader(title)">
    <nav class="navbar">
        <div class="container">
            <h1 th:text="${title}">默认标题</h1>
            <ul>
                <li><a th:href="@{/home}">首页</a></li>
                <li><a th:href="@{/about}">关于我们</a></li>
            </ul>
        </div>
    </nav>
</header>

引入片段:使用th:replace(替换当前标签)、th:insert(插入到当前标签内部)或th:include(插入片段内容,已过时)引入片段:

<!-- src/main/resources/templates/index.html -->
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <title>首页</title>
</head>
<body>
    <!-- 引入头部片段,传递参数"我的网站" -->
    <div th:replace="fragments/header :: siteHeader('我的网站')"></div>
    
    <main>首页内容</main>
    
    <!-- 引入页脚片段(假设已定义footer.html) -->
    <div th:insert="fragments/footer :: siteFooter"></div>
</body>
</html>

关键区别th:replace会替换当前标签(如上述<div>会被<header>替换),而th:insert会保留当前标签,将片段作为子元素插入。

1.1.2 布局继承:实现"母版页"效果

通过Layout Dialect(需额外依赖)可实现类似JSP的"母版页"功能,定义一个基础布局模板,子页面仅需填充特定区域。

步骤1:添加Layout Dialect依赖(Maven):

<dependency>
    <groupId>nz.net.ultraq.thymeleaf</groupId>
    <artifactId>thymeleaf-layout-dialect</artifactId>
    <version>3.1.0</version> <!-- 适配Thymeleaf 3.x -->
</dependency>

步骤2:定义基础布局模板(base.html)

<!-- src/main/resources/templates/layouts/base.html -->
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org"
      xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout">
<head>
    <meta charset="UTF-8">
    <title layout:title-pattern="$CONTENT_TITLE - 我的网站">默认标题</title>
    <link rel="stylesheet" th:href="@{/css/main.css}">
</head>
<body>
    <header th:replace="fragments/header :: siteHeader"></header>
    
    <!-- 内容区域:子页面将替换此标签 -->
    <main layout:fragment="content"></main>
    
    <footer th:replace="fragments/footer :: siteFooter"></footer>
</body>
</html>

步骤3:子页面继承布局并填充内容

<!-- src/main/resources/templates/home.html -->
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org"
      xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout"
      layout:decorate="~{layouts/base.html}"> <!-- 继承基础布局 -->
      
<head>
    <title layout:title-pattern="$CONTENT_TITLE">首页</title> <!-- 页面标题 -->
</head>

<!-- 填充布局中的content片段 -->
<main layout:fragment="content">
    <h2>欢迎来到首页</h2>
    <p th:text="${welcomeMsg}">默认欢迎语</p>
</main>
</html>

效果:子页面会自动包含基础布局中的header、footer和CSS,仅需关注content区域的个性化内容。

1.2 条件判断与循环:动态渲染页面元素

Thymeleaf提供了丰富的条件渲染循环遍历能力,支持复杂逻辑的页面动态展示。

1.2.1 高级条件判断:th:if/th:unless/th:switch

除了基础的th:if="${user != null}",还可结合表达式优先级逻辑运算符实现复杂条件:

<!-- 复杂条件判断 -->
<div th:if="${user != null and user.age >= 18 and user.status == 'ACTIVE'}">
    成年活跃用户:<span th:text="${user.name}"></span>
</div>

<!-- th:unless(与th:if相反) -->
<div th:unless="${user == null}">
    用户已登录
</div>

<!-- th:switch多条件分支 -->
<div th:switch="${user.role}">
    <p th:case="'ADMIN'">管理员权限</p>
    <p th:case="'USER'">普通用户权限</p>
    <p th:case="*">未知权限</p> <!-- 默认分支 -->
</div>
1.2.2 循环遍历与状态变量

使用th:each遍历集合时,可通过状态变量获取循环信息(索引、计数、是否首尾等):

<!-- 遍历用户列表,获取状态变量 -->
<ul>
    <li th:each="user, userStat : ${users}" 
        th:classappend="${userStat.odd} ? 'odd-row' : 'even-row'">
        <!-- 状态变量属性:index(0开始), count(1开始), size(总元素数), first(是否首元素), last(是否尾元素), odd/even(奇偶行) -->
        <span th:text="${userStat.count}">序号</span>: 
        <span th:text="${user.name}">用户名</span>
        <span th:if="${userStat.first}">(首行)</span>
        <span th:if="${userStat.last}">(尾行)</span>
    </li>
</ul>

状态变量默认命名:若未显式指定(如userStat),Thymeleaf会自动生成变量名 + Stat的状态变量(如user.userStat)。

1.3 表达式高级应用:简化数据绑定与URL处理

Thymeleaf的表达式体系(变量表达式${}, 选择表达式*{}, 链接表达式@{}等)支持多种高级用法,提升模板灵活性。

1.3.1 选择表达式(*{}):简化对象属性访问

当需要频繁访问同一对象的多个属性时,*{}可简化代码(需配合th:object指定上下文对象):

<!-- 传统方式:重复写user. -->
<div th:if="${user != null}">
    <p>姓名:<span th:text="${user.name}"></span></p>
    <p>年龄:<span th:text="${user.age}"></span></p>
    <p>邮箱:<span th:text="${user.email}"></span></p>
</div>

<!-- 选择表达式:通过th:object指定对象,后续用*{}访问属性 -->
<div th:if="${user != null}" th:object="${user}">
    <p>姓名:<span th:text="*{name}"></span></p>
    <p>年龄:<span th:text="*{age}"></span></p>
    <p>邮箱:<span th:text="*{email}"></span></p>
</div>
1.3.2 链接表达式(@{…}):动态URL生成与参数拼接

@{}不仅能生成相对路径,还支持参数拼接URL重写(自动添加session ID)和路径变量

<!-- 基础相对路径 -->
<a th:href="@{/home}">首页</a>

<!-- 带查询参数 -->
<a th:href="@{/search(keyword=${query}, page=1)}">搜索</a> 
<!-- 生成:/search?keyword=xxx&page=1 -->

<!-- 路径变量(RESTful风格) -->
<a th:href="@{/users/{id}(id=${user.id})}">查看用户</a> 
<!-- 生成:/users/123(假设user.id=123) -->

<!-- 绝对路径 -->
<img th:src="@{https://example.com/logo.png}" alt="Logo">

1.4 国际化(i18n)支持:多语言页面无缝切换

Thymeleaf通过#messages工具对象和Spring的国际化机制,可轻松实现多语言页面。

1.4.1 配置国际化资源
  1. 创建消息属性文件(放在src/main/resources/i18n目录):

    • messages.properties(默认语言):
      welcome=欢迎访问我的网站
      user.name=用户名
      user.age=年龄
      greeting=你好,{0}!今天是{1}
      
    • messages_en.properties(英文):
      welcome=Welcome to My Website
      user.name=Username
      user.age=Age
      greeting=Hello, {0}! Today is {1}
      
  2. Spring Boot配置application.yml):

    spring:
      messages:
        basename: i18n/messages # 资源文件基础路径
        encoding: UTF-8
        fallback-to-system-locale: false # 不回退到系统默认语言
    
1.4.2 在模板中使用国际化消息

通过#{key}获取消息,支持参数化和动态语言切换:

<!-- 基础国际化消息 -->
<h1 th:text="#{welcome}">欢迎</h1>

<!-- 参数化消息({0}、{1}为占位符) -->
<p th:text="#{greeting(${user.name}, #dates.format(today, 'yyyy-MM-dd'))}">
    你好,用户!今天是2023-01-01
</p>

<!-- 切换语言链接(通过lang参数指定) -->
<a th:href="@{/home(lang=zh_CN)}">中文</a>
<a th:href="@{/home(lang=en)}">English</a>

1.5 高级表单处理:数据绑定与验证反馈

Thymeleaf与Spring MVC无缝集成,支持表单对象绑定字段状态显示验证错误提示

1.5.1 表单对象绑定(th:object/th:field)

使用th:object绑定表单对象,th:field自动生成nameidvalue属性(支持双向绑定):

<!-- Controller传递User对象到模板:model.addAttribute("user", new User()); -->
<form th:action="@{/user/save}" th:object="${user}" method="post">
    <!-- 文本输入框:自动绑定user.name -->
    <div>
        <label th:text="#{user.name}">用户名</label>
        <input type="text" th:field="*{name}" />
    </div>
    
    <!-- 年龄输入框:自动绑定user.age -->
    <div>
        <label th:text="#{user.age}">年龄</label>
        <input type="number" th:field="*{age}" />
    </div>
    
    <!-- 单选框:绑定user.gender(值为"male"或"female") -->
    <div>
        <label>性别</label>
        <input type="radio" th:field="*{gender}" th:value="'male'" /><input type="radio" th:field="*{gender}" th:value="'female'" /></div>
    
    <!-- 下拉框:绑定user.role -->
    <div>
        <label>角色</label>
        <select th:field="*{role}">
            <option th:value="'USER'">普通用户</option>
            <option th:value="'ADMIN'">管理员</option>
        </select>
    </div>
    
    <button type="submit">提交</button>
</form>
1.5.2 表单验证与错误提示

结合Spring Validation注解(如@NotBlank@Min),通过#fields工具对象显示验证错误:

步骤1:实体类添加验证注解

public class User {
    @NotBlank(message = "{user.name.notblank}") // 引用国际化消息
    private String name;
    
    @Min(value = 18, message = "{user.age.min}")
    private Integer age;
    
    // getter/setter
}

步骤2:模板中显示错误信息

<form th:action="@{/user/save}" th:object="${user}" method="post">
    <div>
        <label th:text="#{user.name}">用户名</label>
        <input type="text" th:field="*{name}" />
        <!-- 显示name字段错误 -->
        <p th:if="${#fields.hasErrors('name')}" th:text="#{${#fields.errors('name')}}">
            用户名不能为空
        </p>
    </div>
    
    <div>
        <label th:text="#{user.age}">年龄</label>
        <input type="number" th:field="*{age}" />
        <!-- 显示age字段错误 -->
        <p th:if="${#fields.hasErrors('age')}" th:text="#{${#fields.errors('age')}}">
            年龄不能小于18
        </p>
    </div>
    
    <!-- 显示所有错误(非字段级) -->
    <div th:if="${#fields.hasGlobalErrors()}">
        <p th:each="error : ${#fields.globalErrors()}" th:text="#{${error.message}}">
            全局错误信息
        </p>
    </div>
    
    <button type="submit">提交</button>
</form>

二、Thymeleaf核心工具对象:简化数据处理

Thymeleaf提供了一系列内置工具对象,封装了常用的Java操作(日期、数字、字符串、集合等),可直接在模板中调用,避免在Controller中处理格式化逻辑。

2.1 日期时间工具:#dates

用于日期格式化日期比较获取日期属性(年、月、日等),支持java.util.Datejava.time.LocalDateTime(Thymeleaf 3.x+)。

方法示例描述模板使用输出结果
format(date, pattern)格式化日期th:text="${#dates.format(today, 'yyyy-MM-dd HH:mm:ss')}"2025-07-16 17:56:11
year(date)获取年份th:text="${#dates.year(today)}"2025
create(year, month, day)创建日期th:text="${#dates.create(2025, 7, 16)}"Wed Jul 16 00:00:00 CST 2025
isAfter(date1, date2)判断date1是否在date2之后th:if="${#dates.isAfter(order.createTime, order.payTime)}"-

示例代码

<div>
    <p>当前时间:<span th:text="${#dates.format(now, 'yyyy年MM月dd日 HH:mm:ss')}"></span></p>
    <p>订单创建年份:<span th:text="${#dates.year(order.createTime)}"></span></p>
    <p th:if="${#dates.isBefore(order.createTime, #dates.addDays(now, -7))}">
        订单已超过7天未支付
    </p>
</div>

2.2 数字处理工具:#numbers

用于数字格式化(整数、小数、百分比、货币)和数字运算

方法示例描述模板使用输出结果
formatDecimal(num, integerDigits, decimalDigits)格式化小数th:text="${#numbers.formatDecimal(123.456, 3, 2)}"123.46(3位整数,2位小数)
formatPercent(num, decimalDigits)格式化百分比th:text="${#numbers.formatPercent(0.35, 1)}"35.0%
formatCurrency(num)格式化货币(依赖本地化)th:text="${#numbers.formatCurrency(99.99)}"¥99.99(中文环境)

示例代码

<div>
    <p>商品价格:<span th:text="${#numbers.formatCurrency(product.price)}"></span></p>
    <p>折扣率:<span th:text="${#numbers.formatPercent(product.discount, 0)}"></span></p>
    <p>评分(保留1位小数):<span th:text="${#numbers.formatDecimal(product.score, 1, 1)}"></span></p>
</div>

2.3 字符串工具:#strings

提供字符串常用操作(判空、拼接、截取、替换、大小写转换等)。

方法示例描述模板使用输出结果
isEmpty(str)判断是否为空(null或空字符串)th:if="${#strings.isEmpty(user.nickname)}"-
concat(str1, str2)拼接字符串th:text="${#strings.concat(user.firstName, ' ', user.lastName)}"张 三
substring(str, start, end)截取子串th:text="${#strings.substring('HelloWorld', 0, 5)}"Hello
toUpperCase(str)转大写th:text="${#strings.toUpperCase(user.name)}"ZHANGSAN
replace(str, old, new)替换字符串th:text="${#strings.replace(article.content, '旧文本', '新文本')}"-

示例代码

<div>
    <p th:if="${#strings.isEmpty(user.nickname)}">
        <span th:text="${#strings.defaultString(user.nickname, '匿名用户')}"></span>
    </p>
    <p>用户名(大写):<span th:text="${#strings.toUpperCase(user.name)}"></span></p>
    <p>简介(前20字):<span th:text="${#strings.substring(article.summary, 0, 20)} + '...'"></span></p>
</div>

2.4 集合工具:#lists、#sets、#maps

分别用于ListSetMap的操作,如判空、获取大小、排序、过滤等。

#lists常用方法:
<div>
    <!-- 判断列表是否为空 -->
    <p th:if="${#lists.isEmpty(users)}">暂无用户数据</p>
    
    <!-- 获取列表大小 -->
    <p>用户总数:<span th:text="${#lists.size(users)}"></span></p>
    
    <!-- 排序(需元素实现Comparable) -->
    <ul th:each="user : ${#lists.sort(users)}">
        <li th:text="${user.name}"></li>
    </ul>
    
    <!-- 截取子列表(前5条) -->
    <ul th:each="item : ${#lists.subList(products, 0, 5)}">
        <li th:text="${item.name}"></li>
    </ul>
</div>
#maps常用方法:
<div>
    <!-- 判断Map是否为空 -->
    <p th:if="${#maps.isEmpty(configs)}">暂无配置数据</p>
    
    <!-- 获取Map大小 -->
    <p>配置项数量:<span th:text="${#maps.size(configs)}"></span></p>
    
    <!-- 判断是否包含key -->
    <p th:if="${#maps.containsKey(configs, 'site.title')}">
        网站标题:<span th:text="${configs['site.title']}"></span>
    </p>
</div>

2.5 其他实用工具对象

  • #bools:布尔值处理,如#bools.isTrue(flag)#bools.toInteger(flag)(true→1,false→0)。
  • #arrays:数组操作,如#arrays.length(array)#arrays.contains(array, 'value')
  • #uris:URL编码,如th:href="@{/search(keyword=${#uris.escapeQueryParam(query)})}"(避免URL参数特殊字符问题)。

三、自定义工具对象:扩展Thymeleaf能力

除了内置工具,还可通过Spring Bean定义自定义工具类,让Thymeleaf模板直接调用。

3.1 定义自定义工具类

@Component // 注册为Spring Bean
public class ThymeleafUtils {
    // 示例:格式化手机号(138****1234)
    public String formatPhone(String phone) {
        if (phone == null || phone.length() != 11) {
            return phone;
        }
        return phone.substring(0, 3) + "****" + phone.substring(7);
    }
    
    // 示例:计算两个日期相差天数
    public long daysBetween(Date start, Date end) {
        if (start == null || end == null) {
            return 0;
        }
        return (end.getTime() - start.getTime()) / (1000 * 60 * 60 * 24);
    }
}

3.2 在模板中使用自定义工具

通过@beanName.method()直接调用Spring Bean的方法:

<div>
    <p>手机号:<span th:text="${@thymeleafUtils.formatPhone(user.phone)}"></span></p>
    <p>会员有效期:<span th:text="${@thymeleafUtils.daysBetween(now, user.vipExpireTime)} + ''"></span></p>
</div>

总结:Thymeleaf高级特性与工具对象的价值

Thymeleaf的高级特性(模板布局、片段复用、动态表单)解决了页面复用和动态渲染问题,让模板更清晰、可维护;内置工具对象(#dates、#numbers、#strings等)简化了数据处理逻辑,避免在Controller中编写格式化代码;自定义工具则进一步扩展了模板能力,满足项目特定需求。

掌握这些功能后,你将能构建更优雅、高效的Thymeleaf模板,充分发挥其在Spring Boot项目中的优势。建议结合官方文档(Thymeleaf官方指南)深入学习,探索更多高级用法。

参考资料

  • Thymeleaf官方文档:https://www.thymeleaf.org/documentation.html
  • Thymeleaf Layout Dialect:https://ultraq.github.io/thymeleaf-layout-dialect/
  • Spring Boot + Thymeleaf实战:https://spring.io/guides/gs/serving-web-content/### 2.2 数字工具:#numbers
    用于数字格式化(整数、小数、百分比、货币)和数值计算,支持自定义格式。
方法示例描述模板使用输出结果
formatDecimal(number, integerDigits, decimalDigits)格式化小数${#numbers.formatDecimal(123.456, 3, 2)}00123.46
formatCurrency(number)格式化货币${#numbers.formatCurrency(999.99)}¥999.99
formatPercent(number, decimalDigits)格式化百分比${#numbers.formatPercent(0.123, 1)}12.3%
sequence(from, to, step)生成数字序列${#numbers.sequence(1, 5)}[1,2,3,4,5]

示例代码

<div>
    <p>商品价格:<span th:text="${#numbers.formatCurrency(product.price)}"></span></p>
    <p>折扣率:<span th:text="${#numbers.formatPercent(order.discount, 2)}"></span></p>
    <p>评分:<span th:text="${#numbers.formatDecimal(product.rating, 1, 1)}"></span>/5.0</p>
    
    <!-- 生成1-10的序号列表 -->
    <ul>
        <li th:each="i : ${#numbers.sequence(1, 10)}" th:text="${i}">序号</li>
    </ul>
</div>

2.3 字符串工具:#strings

提供字符串常用操作(判空、截取、拼接、替换等),避免模板中复杂的字符串处理逻辑。

方法示例描述模板使用输出结果
isEmpty(str)判断是否为空字符串${#strings.isEmpty(username)}true/false
abbreviate(str, maxLength)截断字符串并添加省略号${#strings.abbreviate('Hello World', 8)}Hello...
toUpperCase(str)转大写${#strings.toUpperCase(name)}ALICE
concat(str1, str2)拼接字符串${#strings.concat(firstName, ' ', lastName)}Alice Smith
contains(str, fragment)判断是否包含子串${#strings.contains(desc, 'Thymeleaf')}true/false

示例代码

<div>
    <p th:if="${#strings.isEmpty(user.nickname)}">
        <span th:text="${#strings.defaultString(user.nickname, '匿名用户')}"></span>
    </p>
    
    <p>商品描述:<span th:text="${#strings.abbreviate(product.desc, 50)}"></span></p>
    
    <p th:text="${#strings.concat('欢迎 ', user.name, ' 登录系统')}"></p>
    
    <div th:if="${#strings.containsIgnoreCase(tag, 'spring')}">
        <span class="tag">Spring相关</span>
    </div>
</div>

2.4 集合工具:#lists、#maps

2.4.1 列表工具(#lists)

处理List集合的常用操作(判空、排序、截取、统计等)。

方法示例描述模板使用输出结果
isEmpty(list)判断列表是否为空${#lists.isEmpty(users)}true/false
size(list)获取列表大小${#lists.size(products)}10
sort(list)自然排序${#lists.sort(numbers)}[1,3,5]
contains(list, element)判断是否包含元素${#lists.contains(roles, 'ADMIN')}true/false

示例代码

<div th:if="${not #lists.isEmpty(products)}">
    <p>商品总数:<span th:text="${#lists.size(products)}"></span></p>
    
    <ul>
        <li th:each="product : ${#lists.sort(products)}" th:text="${product.name}">商品名称</li>
    </ul>
    
    <p th:if="${#lists.contains(products, featuredProduct)}">
        包含推荐商品
    </p>
</div>
2.4.2 映射工具(#maps)

处理Map集合的键值对操作。

方法示例描述模板使用输出结果
size(map)获取Map大小${#maps.size(config)}5
containsKey(map, key)判断是否包含键${#maps.containsKey(settings, 'darkMode')}true/false
values(map)获取所有值${#maps.values(userPreferences)}[true, 'blue', 16]

示例代码

<div th:if="${#maps.size(settings) > 0}">
    <p>系统配置项:<span th:text="${#maps.size(settings)}"></span></p>
    
    <div th:if="${#maps.containsKey(settings, 'theme')}">
        当前主题:<span th:text="${settings.theme}"></span>
    </div>
    
    <ul>
        <li th:each="value : ${#maps.values(settings)}" th:text="${value}">配置值</li>
    </ul>
</div>

三、综合实战案例:用户管理系统页面

3.1 需求描述

实现一个用户管理页面,包含以下功能:

  • 复用公共导航栏和页脚
  • 展示用户列表(带分页、奇偶行样式)
  • 用户搜索(支持关键词过滤)
  • 添加用户表单(带数据验证)
  • 国际化支持(中英文切换)

3.2 实现步骤

步骤1:创建基础布局和片段

导航栏片段(fragments/header.html)

<header th:fragment="siteHeader">
    <nav class="navbar">
        <div class="container">
            <a th:href="@{/}" class="logo">UserAdmin</a>
            <div class="menu">
                <a th:href="@{/users}">用户管理</a>
                <a th:href="@{/roles}">角色管理</a>
                <a th:href="@{/users(lang=zh_CN)}">中文</a>
                <a th:href="@{/users(lang=en)}">English</a>
            </div>
        </div>
    </nav>
</header>
步骤2:用户列表页面(users.html)
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org"
      xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout"
      layout:decorate="~{layouts/base.html}">
<head>
    <title layout:title-pattern="$CONTENT_TITLE">用户管理</title>
</head>

<main layout:fragment="content">
    <div class="container">
        <div class="search-bar">
            <form th:action="@{/users}" method="get">
                <input type="text" name="keyword" th:value="${keyword}" 
                       placeholder="#{search.placeholder}">
                <button type="submit">#{search.button}</button>
            </form>
        </div>

        <div class="user-table">
            <table>
                <thead>
                    <tr>
                        <th>ID</th>
                        <th th:text="#{user.name}">用户名</th>
                        <th th:text="#{user.email}">邮箱</th>
                        <th th:text="#{user.status}">状态</th>
                        <th th:text="#{user.registerTime}">注册时间</th>
                    </tr>
                </thead>
                <tbody>
                    <tr th:each="user, stat : ${users}" 
                        th:classappend="${stat.odd} ? 'odd' : 'even'">
                        <td th:text="${user.id}">1</td>
                        <td th:text="${user.name}">张三</td>
                        <td th:text="${user.email}">zhangsan@example.com</td>
                        <td>
                            <span th:if="${user.active}" class="status active" 
                                  th:text="#{status.active}">启用</span>
                            <span th:unless="${user.active}" class="status inactive" 
                                  th:text="#{status.inactive}">禁用</span>
                        </td>
                        <td th:text="${#dates.format(user.registerTime, 'yyyy-MM-dd')}">
                            2025-01-01
                        </td>
                    </tr>
                    <tr th:if="${#lists.isEmpty(users)}">
                        <td colspan="5" th:text="#{table.empty}">暂无数据</td>
                    </tr>
                </tbody>
            </table>
        </div>

        <div class="pagination">
            <a th:href="@{/users(page=${page-1}, keyword=${keyword})}" 
               th:unless="${page == 0}">#{pagination.prev}</a>
            <span th:text="#{pagination.page(${page+1}, ${totalPages})}">第1页/共5页</span>
            <a th:href="@{/users(page=${page+1}, keyword=${keyword})}" 
               th:unless="${page+1 >= totalPages}">#{pagination.next}</a>
        </div>
    </div>
</main>
</html>
步骤3:添加用户表单(user-form.html)
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org"
      xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout"
      layout:decorate="~{layouts/base.html}">
<head>
    <title layout:title-pattern="$CONTENT_TITLE">添加用户</title>
</head>

<main layout:fragment="content">
    <div class="container">
        <h2 th:text="#{user.add}">添加用户</h2>
        
        <form th:action="@{/users/save}" th:object="${user}" method="post" class="user-form">
            <div class="form-group">
                <label th:text="#{user.name}">用户名</label>
                <input type="text" th:field="*{name}" class="form-control">
                <p th:if="${#fields.hasErrors('name')}" class="error" 
                   th:text="#{${#fields.errors('name')}}">用户名不能为空</p>
            </div>
            
            <div class="form-group">
                <label th:text="#{user.email}">邮箱</label>
                <input type="email" th:field="*{email}" class="form-control">
                <p th:if="${#fields.hasErrors('email')}" class="error" 
                   th:text="#{${#fields.errors('email')}}">邮箱格式不正确</p>
            </div>
            
            <div class="form-group">
                <label th:text="#{user.age}">年龄</label>
                <input type="number" th:field="*{age}" class="form-control">
                <p th:if="${#fields.hasErrors('age')}" class="error" 
                   th:text="#{${#fields.errors('age')}}">年龄必须大于18</p>
            </div>
            
            <div class="form-actions">
                <button type="submit" class="btn primary" th:text="#{button.save}">保存</button>
                <a th:href="@{/users}" class="btn secondary" th:text="#{button.cancel}">取消</a>
            </div>
        </form>
    </div>
</main>
</html>

四、总结与进阶学习

4.1 核心知识点回顾

本文详细介绍了Thymeleaf的高级特性和工具对象,包括:

  • 模板布局:通过片段复用和Layout Dialect实现页面结构复用
  • 动态渲染:条件判断、循环遍历及状态变量的高级应用
  • 表达式语言:选择表达式、链接表达式的简化用法
  • 国际化:多语言配置与消息参数化
  • 表单处理:数据绑定、验证反馈与错误提示
  • 工具对象:#dates、#numbers、#strings等内置工具的实用方法

4.2 进阶学习资源

  1. 官方文档Thymeleaf官方指南
  2. Layout DialectThymeleaf Layout Dialect
  3. Spring集成Spring Boot + Thymeleaf实战
  4. 性能优化:模板缓存配置、片段表达式预编译

4.3 常见问题解决方案

  • 模板渲染慢:启用Thymeleaf缓存(spring.thymeleaf.cache=true
  • 布局冲突:使用th:remove="all-but-first"清理重复元素
  • 复杂逻辑处理:避免在模板中写复杂逻辑,通过Controller准备数据
  • 国际化乱码:确保消息文件编码为UTF-8,并在配置中显式指定

通过掌握这些高级特性和工具对象,你可以构建更灵活、可维护的Thymeleaf模板,提升Spring Boot项目的视图层开发效率。建议结合实际项目多练手,深入理解Thymeleaf的设计思想。## 补充:Thymeleaf其他实用高级特性

内联文本与JavaScript集成

Thymeleaf支持内联表达式,简化模板中的文本渲染和JavaScript变量绑定:

<!-- 内联文本(等价于th:text) -->
<p>欢迎 [[${user.name}]] 登录系统</p>

<!-- JavaScript变量绑定 -->
<script th:inline="javascript">
    const user = /*[[${user}]]*/ {}; // 将Java对象转换为JSON
    const baseUrl = /*[[@{/api}]]*/ ''; // 动态生成基础URL
    
    console.log('用户名:', user.name);
    console.log('API地址:', baseUrl);
</script>

模板注释与条件注释

Thymeleaf提供两种注释方式,支持开发调试和条件渲染:

<!-- 标准HTML注释:会被浏览器解析,但Thymeleaf会忽略其中的表达式 -->
<!-- 用户ID: ${user.id} -->

<!--/* Thymeleaf解析注释:仅模板引擎可见,不会输出到HTML */-->
<!--/* 这部分内容不会出现在最终HTML中 */-->

<!--[if IE]>
    <!-- IE条件注释:仅IE浏览器可见 -->
    <link rel="stylesheet" th:href="@{/css/ie-compatible.css}">
<![endif]-->

片段表达式的参数传递与默认值

片段引入时可传递动态参数,并设置默认值:

<!-- 定义带默认参数的片段 -->
<nav th:fragment="breadcrumb(homeText='首页', currentText='当前页')">
    <ol>
        <li><a th:text="${homeText}" th:href="@{/}"></a></li>
        <li class="active" th:text="${currentText}"></li>
    </ol>
</nav>

<!-- 引入片段并覆盖参数 -->
<div th:replace="fragments/breadcrumb :: breadcrumb(homeText='控制台', currentText='用户列表')"></div>

模板缓存与性能优化

在Spring Boot中配置Thymeleaf缓存,提升生产环境性能:

# application.yml
spring:
  thymeleaf:
    cache: true # 生产环境启用缓存
    mode: HTML # 使用HTML5模式,避免严格XML校验
    encoding: UTF-8
    prefix: classpath:/templates/
    suffix: .html
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值