1. Thymeleaf 基础入门
1.1 什么是Thymeleaf?
Thymeleaf是一个现代化的Java模板引擎,主要用于Web和独立环境开发。它最大的特点是能够直接在浏览器中显示静态原型,同时又能作为动态模板在后端渲染。我在实际项目中使用Thymeleaf已经超过5年,发现它特别适合Spring Boot项目的前端开发。
Thymeleaf的核心优势在于:
- 自然的模板语法:HTML标签加上Thymeleaf属性,既保持了HTML的原始结构,又实现了动态功能
- 强大的表达式语言:支持变量、选择变量、国际化等多种表达式
- 与Spring生态完美集成:特别是Spring Boot项目中,几乎零配置即可使用
1.2 环境搭建与配置
在Spring Boot项目中集成Thymeleaf非常简单。首先需要在pom.xml中添加starter依赖:
xml复制<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
Spring Boot会自动配置Thymeleaf,默认模板位置是src/main/resources/templates/,静态资源位置是src/main/resources/static/。如果需要自定义配置,可以在application.properties中添加:
properties复制# 模板文件后缀
spring.thymeleaf.suffix=.html
# 模板编码
spring.thymeleaf.encoding=UTF-8
# 模板模式
spring.thymeleaf.mode=HTML
# 开发时关闭缓存
spring.thymeleaf.cache=false
提示:开发阶段建议关闭缓存,这样修改模板后刷新页面就能看到变化,不需要重启应用。
2. Thymeleaf核心语法详解
2.1 变量表达式(${})
变量表达式是Thymeleaf最常用的语法,用于获取后端传递的数据。基本语法是th:text="${变量名}"。
html复制<!-- 简单变量 -->
<div th:text="${message}">默认消息</div>
<!-- 对象属性 -->
<div th:text="${user.name}">默认用户名</div>
<div th:text="${user['age']}">默认年龄</div>
在后端Controller中传递数据:
java复制@GetMapping("/profile")
public String profile(Model model) {
User user = new User("李四", 25);
model.addAttribute("user", user);
model.addAttribute("message", "欢迎访问个人主页");
return "profile";
}
注意事项:
- 如果变量为null,Thymeleaf会显示标签内的默认内容
- 对象属性访问支持点语法和方括号语法
- th:text会转义HTML标签,如果需要显示HTML内容,使用th:utext
2.2 选择变量表达式(*{})
选择变量表达式可以简化对象属性的访问,特别适合表单处理场景。需要先使用th:object指定对象。
html复制<form th:object="${user}">
<input type="text" th:field="*{name}">
<input type="number" th:field="*{age}">
</form>
等价于:
html复制<form>
<input type="text" th:value="${user.name}">
<input type="number" th:value="${user.age}">
</form>
实操心得:在处理复杂表单时,选择变量表达式可以显著减少代码量,提高可读性。
2.3 链接表达式(@{})
链接表达式用于生成URL,会自动处理上下文路径,避免硬编码。
html复制<!-- 基本链接 -->
<a th:href="@{/home}">首页</a>
<!-- 带参数链接 -->
<a th:href="@{/user/details(id=${user.id},type='vip')}">用户详情</a>
<!-- 静态资源 -->
<link th:href="@{/css/style.css}" rel="stylesheet">
<script th:src="@{/js/app.js}"></script>
常见问题:如果URL参数中包含特殊字符,Thymeleaf会自动进行URL编码。如果需要禁用编码,可以使用双括号语法:@{/(id=${user.id})}
3. Thymeleaf高级功能
3.1 条件判断
Thymeleaf提供了多种条件判断方式:
html复制<!-- th:if / th:unless -->
<div th:if="${user.active}">活跃用户</div>
<div th:unless="${user.active}">非活跃用户</div>
<!-- th:switch -->
<div th:switch="${user.role}">
<span th:case="'admin'">管理员</span>
<span th:case="'user'">普通用户</span>
<span th:case="*">未知角色</span>
</div>
注意事项:th:case的值如果是字符串,需要用单引号括起来;th:case="*"表示默认情况。
3.2 循环遍历
th:each指令可以遍历各种集合类型:
html复制<!-- 遍历List -->
<ul>
<li th:each="item : ${items}" th:text="${item}">默认项</li>
</ul>
<!-- 遍历Map -->
<table>
<tr th:each="entry : ${map}">
<td th:text="${entry.key}"></td>
<td th:text="${entry.value}"></td>
</tr>
</table>
<!-- 使用状态变量 -->
<ul>
<li th:each="user, stat : ${users}"
th:text="${stat.count} + '. ' + ${user.name}"
th:class="${stat.odd} ? 'odd' : 'even'">
默认用户
</li>
</ul>
状态变量提供了多个有用属性:
- index: 当前迭代索引(0开始)
- count: 当前迭代计数(1开始)
- size: 集合大小
- even/odd: 是否为偶数/奇数行
- first/last: 是否为第一个/最后一个元素
3.3 模板片段
Thymeleaf支持模板片段复用,这是保持DRY(Don't Repeat Yourself)原则的重要特性。
定义片段(fragments/header.html):
html复制<header th:fragment="mainHeader">
<h1>网站标题</h1>
<nav>
<a th:href="@{/}">首页</a>
<a th:href="@{/about}">关于</a>
</nav>
</header>
使用片段:
html复制<!-- 插入片段 -->
<div th:insert="~{fragments/header :: mainHeader}"></div>
<!-- 替换当前元素 -->
<div th:replace="~{fragments/header :: mainHeader}"></div>
最佳实践:将公共部分(页眉、页脚、导航栏)提取为片段,可以显著减少重复代码,也便于统一修改。
4. Thymeleaf实用技巧
4.1 内联表达式
内联表达式允许在HTML文本或JavaScript中直接使用Thymeleaf表达式。
html复制<!-- 文本内联 -->
<p>欢迎, [[${user.name}]]!</p>
<!-- JavaScript内联 -->
<script th:inline="javascript">
var userId = /*[[${user.id}]]*/ 0;
var userName = /*[[${user.name}]]*/ 'Guest';
function greet() {
alert('Hello, ' + userName + '!');
}
</script>
注意事项:[[...]]会对HTML进行转义,[(...)]则不会转义。JavaScript内联表达式中的/[[...]]/语法是为了在没有服务器渲染时提供可读的默认值。
4.2 工具类
Thymeleaf提供了一系列实用的工具类:
html复制<!-- 字符串处理 -->
<div th:text="${#strings.toUpperCase(user.name)}"></div>
<div th:if="${#strings.isEmpty(user.bio)}">暂无简介</div>
<!-- 日期格式化 -->
<div th:text="${#dates.format(user.createDate, 'yyyy-MM-dd HH:mm')}"></div>
<!-- 数字格式化 -->
<div th:text="${#numbers.formatDecimal(user.balance, 1, 2)}"></div>
<!-- 集合工具 -->
<div th:if="${#lists.isEmpty(user.friends)}">暂无好友</div>
常用工具类包括:
- #strings: 字符串操作
- #numbers: 数字格式化
- #dates: 日期处理
- #lists: 集合操作
- #arrays: 数组操作
- #objects: 对象操作
4.3 表单处理
Thymeleaf与Spring MVC的表单绑定功能配合得非常好:
html复制<form th:action="@{/user/save}" th:object="${user}" method="post">
<input type="text" th:field="*{name}">
<input type="email" th:field="*{email}">
<input type="checkbox" th:field="*{subscribed}">
<button type="submit">保存</button>
</form>
避坑指南:使用th:field时,表单元素必须有name属性,Thymeleaf会自动生成id和name属性,并与后端对象属性绑定。
5. 性能优化与最佳实践
5.1 缓存策略
在生产环境中,Thymeleaf模板缓存可以显著提高性能:
properties复制# 生产环境开启缓存
spring.thymeleaf.cache=true
性能提示:开发时关闭缓存,生产环境开启缓存。如果使用配置中心,可以通过环境变量动态配置。
5.2 模板布局
对于复杂的页面结构,可以使用布局方言(thymeleaf-layout-dialect):
xml复制<dependency>
<groupId>nz.net.ultraq.thymeleaf</groupId>
<artifactId>thymeleaf-layout-dialect</artifactId>
</dependency>
定义布局(layout.html):
html复制<!DOCTYPE html>
<html xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout">
<head>
<title layout:title-pattern="$CONTENT_TITLE - $LAYOUT_TITLE">默认标题</title>
</head>
<body>
<header>...</header>
<section layout:fragment="content"></section>
<footer>...</footer>
</body>
</html>
使用布局:
html复制<html xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout"
layout:decorate="~{layout}">
<head>
<title>页面标题</title>
</head>
<body>
<section layout:fragment="content">
<!-- 页面特有内容 -->
</section>
</body>
</html>
5.3 错误处理
Thymeleaf提供了友好的错误页面支持:
java复制@Controller
public class ErrorController implements org.springframework.boot.web.servlet.error.ErrorController {
@RequestMapping("/error")
public String handleError(HttpServletRequest request) {
// 根据状态码返回不同错误页面
Object status = request.getAttribute(RequestDispatcher.ERROR_STATUS_CODE);
if (status != null) {
int statusCode = Integer.parseInt(status.toString());
if (statusCode == 404) return "error/404";
if (statusCode == 500) return "error/500";
}
return "error/default";
}
}
对应的错误模板(error/404.html):
html复制<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<title>页面不存在</title>
</head>
<body>
<h1>404 - 页面不存在</h1>
<p th:text="${#dates.createNow()}">当前时间</p>
<a th:href="@{/}">返回首页</a>
</body>
</html>
在实际项目中,我发现合理使用Thymeleaf的这些特性可以大大提高开发效率和代码质量。特别是在团队协作中,模板的复用和清晰的表达式语法可以减少很多沟通成本。