网站首页 > 精选文章 / 正文
Thymeleaf 是一个现代化的服务器端 Java 模板引擎,支持 HTML、XML、JavaScript、CSS 甚至纯文本。以下是 Thymeleaf 语法的全面详解,包含所有属性和复杂用法。
一、基础语法
1. 标准表达式语法
Thymeleaf 提供了多种表达式类型:
<p th:text="${message}">默认消息</p>
1.1 变量表达式 ${...}
用于访问变量和模型属性:
<span th:text="${user.name}">用户名</span>
1.2 选择表达式 *{...}
用于选择当前选择的对象:
<div th:object="${user}">
<p th:text="*{name}">姓名</p>
<p th:text="*{age}">年龄</p>
</div>
1.3 消息表达式 #{...}
用于国际化消息:
<p th:text="#{welcome.message}">欢迎消息</p>
1.4 链接表达式 @{...}
用于 URL 链接:
<a th:href="@{/user/details(id=${user.id})}">用户详情</a>
1.5 片段表达式 ~{...}
用于模板片段:
<div th:insert="~{commons :: footer}"></div>
2. 字面量
- 文本字面量: '单引号内容'
- 数字字面量: 123, 3.14
- 布尔字面量: true, false
- null 字面量: null
<span th:text="'固定文本'"></span>
<span th:text="2019"></span>
<span th:text="true"></span>
3. 文本操作
- 字符串连接: +
- 字面量替换: |...|
<span th:text="'欢迎 ' + ${user.name}"></span>
<span th:text="|欢迎 ${user.name}|"></span>
4. 算术运算
- 基本运算: +, -, *, /, %
<span th:text="${count + 1}"></span>
5. 布尔运算
- 比较: >, <, >=, <=, ==, !=
- 逻辑运算: and, or, !, not
<div th:if="${user.age > 18}">成年人</div>
<div th:unless="${not user.active}">活跃用户</div>
6. 条件运算
- if-then: (if) ? (then)
- if-then-else: (if) ? (then) : (else)
- 默认值: (value) ?: (defaultvalue)
<span th:text="${user.admin} ? '管理员' : '普通用户'"></span>
<span th:text="${user.name} ?: '匿名用户'"></span>
二、Thymeleaf 属性详解
1. 核心属性
th:text
设置元素的文本内容,会转义 HTML 标签:
<p th:text="${htmlContent}">默认文本</p>
th:utext
设置元素的文本内容,不转义 HTML 标签:
<p th:utext="${htmlContent}">默认文本</p>
th:value
设置表单元素的值:
<input type="text" th:value="${user.name}" />
th:with
定义局部变量:
<div th:with="first=${user.firstName}, last=${user.lastName}">
<span th:text="${first}"></span>
<span th:text="${last}"></span>
</div>
th:attr
设置任意属性:
<img th:attr="src=@{/images/logo.png}, title=${logoTitle}, alt=${logoAlt}" />
2. 条件属性
th:if/ th:unless
条件显示元素:
<div th:if="${user.admin}">管理员面板</div>
<div th:unless="${user.blocked}">正常用户</div>
th:switch/ th:case
多条件选择:
<div th:switch="${user.role}">
<p th:case="'admin'">管理员</p>
<p th:case="'manager'">经理</p>
<p th:case="*">普通用户</p>
</div>
3. 循环属性
th:each
循环遍历:
<ul>
<li th:each="item : ${items}" th:text="${item.name}">项目名称</li>
</ul>
循环状态变量:
<table>
<tr th:each="user, stat : ${users}">
<td th:text="${stat.index}">序号</td>
<td th:text="${user.name}">姓名</td>
<td th:text="${stat.odd} ? '奇数行' : '偶数行'">行类型</td>
</tr>
</table>
4. 模板布局属性
th:insert
插入模板片段:
<div th:insert="~{fragments/header :: main-header}"></div>
th:replace
替换当前元素为模板片段:
<footer th:replace="~{fragments/footer :: main-footer}"></footer>
th:include
包含模板片段的内容(已废弃,推荐使用 th:insert 或 th:replace)
5. 表单属性
th:field
绑定表单字段:
<input type="text" th:field="*{name}" />
th:action
设置表单提交地址:
<form th:action="@{/user/save}" method="post">
<!-- 表单内容 -->
</form>
th:object
设置表单绑定对象:
<form th:object="${user}" method="post">
<input type="text" th:field="*{name}" />
<input type="text" th:field="*{email}" />
</form>
6. 链接和 URL 属性
th:href
设置链接地址:
<a th:href="@{/user/{id}/profile(id=${user.id})}">用户资料</a>
th:src
设置资源地址:
<img th:src="@{/images/logo.png}" />
7. 片段表达式属性
th:remove
移除模板片段:
<table>
<tr th:remove="all">
<td>将被移除的行</td>
</tr>
<tr th:remove="all-but-first">
<td>第一行保留</td>
</tr>
</table>
可选值:
- all:移除当前标签及其所有子标签
- body:不移除当前标签但移除所有子标签
- tag:移除当前标签但不移除子标签
- all-but-first:移除除第一个外的所有子标签
- none:什么都不移除
8. 其他属性
th:classappend
追加 CSS 类:
<div th:classappend="${user.active} ? 'active' : 'inactive'"></div>
th:styleappend
追加样式:
<div th:styleappend="'color:' + ${user.color}"></div>
th:lang
设置语言:
<html th:lang="${#locale.language}"></html>
th:title
设置 title 属性:
<img th:title="${imageTitle}" />
th:alt
设置 alt 属性:
<img th:alt="${imageAltText}" />
th:onclick
设置 onclick 事件:
<button th:onclick="'alert(\'' + ${message} + '\')'">点击</button>
th:inline
设置内联模式:
<script th:inline="javascript">
var user = [[${user}]];
console.log(user.name);
</script>
支持的值:
- text:文本内联
- javascript:JavaScript 内联
- none:禁用内联
- dart:Dart 内联(已废弃)
三、复杂用法
1. 复杂表达式和实用对象
Thymeleaf 提供了一系列实用对象:
<p th:text="${#strings.isEmpty(user.name)}">检查是否为空</p>
<p th:text="${#lists.size(user.roles)}">角色数量</p>
<p th:text="${#dates.format(user.birthday, 'yyyy-MM-dd')}">生日</p>
<p th:text="${#numbers.formatDecimal(price, 1, 2)}">格式化数字</p>
<p th:text="${#calendars.createNow()}">当前时间</p>
常用实用对象:
- #strings:字符串工具
- #numbers:数字工具
- #bools:布尔工具
- #arrays:数组工具
- #lists:列表工具
- #sets:集合工具
- #maps:映射工具
- #dates:日期工具(java.util.Date)
- #calendars:日历工具(java.util.Calendar)
- #temporals:Java8 时间工具(java.time.*)
- #objects:对象工具
- #ids:ID生成工具
2. 内联 JavaScript 和 CSS
JavaScript 内联:
<script th:inline="javascript">
var user = [[${user}]];
var message = [[#{welcome.message}]];
console.log(user.name + ": " + message);
</script>
CSS 内联:
<style th:inline="text">
.[[${mainClass}]] {
color: [[${mainColor}]];
}
</style>
3. 模板布局
定义片段:
fragments/header.html:
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head th:fragment="common-header">
<meta charset="UTF-8"/>
<title th:text="${title}">默认标题</title>
</head>
使用片段:
<head th:replace="~{fragments/header :: common-header}">
<!-- 将被替换 -->
</head>
4. 参数化片段
定义带参数的片段:
<div th:fragment="alert (type, message)">
<div class="alert alert-[[${type}]]">
[[${message}]]
</div>
</div>
使用带参数的片段:
<div th:replace="~{:: alert('success', '操作成功')}"></div>
5. 高级表单处理
多复选框绑定:
<input type="checkbox" th:field="*{roles}" th:value="'ADMIN'" /> 管理员
<input type="checkbox" th:field="*{roles}" th:value="'USER'" /> 普通用户
<input type="checkbox" th:field="*{roles}" th:value="'GUEST'" /> 访客
单选按钮绑定:
<input type="radio" th:field="*{gender}" th:value="'MALE'" /> 男
<input type="radio" th:field="*{gender}" th:value="'FEMALE'" /> 女
6. 复杂条件判断
使用 Elvis 运算符:
<span th:text="${user.name} ?: '匿名用户'"></span>
安全导航运算符:
<span th:text="${user?.address?.street}"></span>
7. 集合投影和选择
集合投影:
<div th:each="name : ${#strings.listSplit(user.fullName, ' ')}">
<span th:text="${name}"></span>
</div>
集合选择:
<div th:each="user : ${users.?[age > 18]}">
<span th:text="${user.name}">成年人</span>
</div>
8. 预处理表达式
在表达式执行前进行预处理:
<p th:text="${__#{${user.lang}+'.welcome.message'}__}">欢迎消息</p>
9. 自定义属性处理器
通过方言扩展可以创建自定义属性处理器:
public class MyDialect extends AbstractProcessorDialect {
public MyDialect() {
super("My Dialect", "my", 1000);
}
@Override
public Set<IProcessor> getProcessors(String dialectPrefix) {
Set<IProcessor> processors = new HashSet<>();
processors.add(new MyAttributeTagProcessor(dialectPrefix));
return processors;
}
}
然后在模板中使用:
<div my:customattr="${value}">自定义属性</div>
四、性能优化技巧
- 缓存模板:在生产环境中启用模板缓存
- spring.thymeleaf.cache=true
- 使用片段缓存:
- <div th:replace="~{fragments/menu :: main-menu}" th:cacheable="true"></div>
- 避免复杂表达式:尽量减少模板中的复杂逻辑
- 合理使用内联:只在必要时使用内联表达式
- 预编译模板:在构建时预编译模板
五、常见问题解决方案
- 表达式不解析:
- 确保 HTML 文件有 xmlns:th="http://www.thymeleaf.org" 声明
- 检查表达式语法是否正确
- 表单绑定失败:
- 确保表单有 th:object 属性
- 检查字段名称是否匹配
- 国际化消息不显示:
- 检查消息文件位置和命名
- 确保有正确的区域设置解析器
- 片段无法加载:
- 检查片段路径是否正确
- 确保片段文件存在
- 性能问题:
- 启用模板缓存
- 减少模板中的复杂逻辑
六、最佳实践
- 保持模板简洁:将复杂逻辑移到控制器或服务层
- 合理组织模板:
- 使用片段组织可重用部分
- 创建布局模板
- 使用注释:
- <!--/* 这是服务器端可见的注释 */-->
<!-- 这是客户端可见的注释 --> - 安全性考虑:
- 使用 th:text 而不是 th:utext 除非必要
- 对用户输入进行适当转义
- 测试模板:
- 编写模板测试用例
- 验证不同条件下的输出
通过掌握这些 Thymeleaf 语法和技巧,您可以创建灵活、高效且易于维护的模板。记住,模板的主要职责是展示数据,复杂的业务逻辑应该放在 Java 代码中。
头条对markdown的文章显示不太友好,想了解更多的可以关注微信公众号:“Eric的技术杂货库”,后期会有更多的干货以及资料下载。
Tags:thymeleaf foreach
猜你喜欢
- 2025-05-23 Spring Boot 3.x 新特性详解:从基础到高级实战