Springboot中引入Thymeleaf
Thymeleaf作为spring官方推荐的模板引擎,在spring体系中使用异常方便。这里以gradle构建的项目为例来说明。
首先,你要先修改build.gradle引入Springboot对Thymeleaf提供的依赖包。在dependencies中增加如下配置。
compile('org.springframework.boot:spring-boot-starter-thymeleaf')
等待gradle帮你自己下载完依赖包后,你可以看到引入的Thymeleaf的版本。

嗯?springboot1.5.7默认引用的Thymeleaf依赖包居然还是2.1.5版本。最新的Thymeleaf不是已经更新3.x版本了么。如果我想使用最新版的Thymeleaf要怎么办呢。
在build.gradle文件中,buildscript下增加配置,完整的配置如下图
ext['thymeleaf.version'] = '3.0.7.RELEASE'
ext['thymeleaf-layout-dialect.version'] = '2.2.2'

等待gradle下载完成,你可以看到引入的Thymeleaf已经是最新版本了。
快速入门
接下来要在项目中使用Thymeleaf了,这里用一个简单的单表查询来举个栗子。
一般来说,开发一个需要渲染数据的页面,分为三个步骤。
1.开发静态页面,即常说的模型。
2.获取数据。
3.使用数据对静态页面进行渲染。
这里我们先做第一个步骤,开发静态页面。为了简单,就不做任何css了,下面是页面的源码。
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>标题</title>
</head>
<body>
<strong>标题</strong>
<form action="list.html" method="post">
<input type="hidden" name="pageNumber">
用户名:<input type="text" name="username">
<br/>
姓名:<input type="text" name="name">
<br/>
<button type="submit">提交</button> <button type="reset">重置</button>
</form>
<table>
<thead>
<tr>
<th class="am-hide-sm-only">id</th>
<th>用户名</th>
<th>姓名</th>
<th class="am-hide-sm-only">电话</th>
<th class="am-hide-sm-only">邮箱</th>
<th class="am-hide-sm-only">是否可用</th>
<th>操作</th>
</tr>
</thead>
<tbody>
<tr>
<td>id</td>
<td>用户名</td>
<td>姓名</td>
<td>电话</td>
<td>邮箱</td>
<td>
<span>可用</span><span>不可用</span>
</td>
<td><button>修改</button><button>删除</button></td>
</tr>
</tbody>
</table>
</body>
</html>
直接使用浏览器打开该页面,长成这样。

现在有了静态页面,该获取数据了。下面是controller层的代码。
/**
* 用户管理
*/
@Controller
@RequestMapping("/users")
public class UserController
{
@Autowired
private UserRepository userRepository;
@Value("${pageSize}")
private Integer pageSize;
/**
* 分页查询信息
*/
@RequestMapping(method = {RequestMethod.GET, RequestMethod.POST})
public String list(Model model, User user, @RequestParam(value = "pageNumber", required = false, defaultValue = "0") Integer pageNumber)
{
ExampleMatcher matcher = ExampleMatcher.matching().withStringMatcher(ExampleMatcher.StringMatcher.CONTAINING);
PageRequest pageRequest = new PageRequest(pageNumber, pageSize);
Page<User> page = userRepository.findAll(Example.of(user, matcher), pageRequest);
//分页查询数据
model.addAttribute("page", page);
//查询条件
model.addAttribute("user", user);
//页面标题
model.addAttribute("title", "用户管理");
//转到待渲染模板,所有模板都在templates文件夹下,users/list指templates文件夹下的users文件夹下的list.html页面。
return "users/list";
}
}
这里使用spring-data-jpa从数据库里查询到了记录并和查询条件、页面标题一起转到待渲染的模板。这里,我们将刚才的静态页面文件复制到对应的位置。如下图。

下面,我们要对该文件进行适当的改造,使之成为一个Thymeleaf模板文件。先贴上改造后的文件。
···
用户名 | 姓名 | 操作 | ||||
---|---|---|---|---|---|---|
id | 用户名 | 姓名 | 电话 | 邮箱 | 可用不可用 |
可以看到,我们对html代码的结构丝毫未改动,只是在一些标签里面添加了th:xxx="yyy"的属性。
我们重新使用浏览器打开Thymeleaf改造过的html文件。发现虽然我们添加了那么多th:xxx="yyy"的标签,但是,页面居然和之前一模一样。

下面我们启动服务,通过controller定义的那个url来访问渲染后的页面。

同一个文件,浏览器直接打开就是原型,服务器渲染后打开就是真实的功能页面。
这里我们就可以看出Thymeleaf的一个核心功能,就是将其逻辑注入到模板文件中,不会影响模板被用作设计原型。做到了原型即页面。
Thymeleaf的核心语法就是th:xxx="yyy"
,即设置html标签中xxx属性的值为yyy对应的值
设置属性
我们先来说一说th:xxx的部分,即设置属性。
Thymeleaf的核心功能就是通过在html标签里面追加属性。可以设置的属性非常多,详细的可以参考 Thymeleaf所有属性的还没发文档。这里我们就挑选些常用的举几个例子,其他大家可以举一反三推断出用法。
th:object="yyy" 将对象作为一个范围内可用的变量。一般和选择表达式*{zzz}配合使用,选择表达式后面会讲到。
th:text="yyy" 这个属性可以添加到几乎所有分为头尾两部分<></>的html标签中,如<title></title>、<td><td/>等。th:text="yyy"的作用是把表达式yyy对应的值添加到标签的中间。
如<td th:text="user">用户名</td>渲染后就是<td>user<td/>。
th:value="${title}" 这个属性一般和<input />标签搭配使用,用来设置<input />标签的value值。
如<input th:value="username" />渲染后就是<input value="username" />。
我们先来说一说th:xxx
的部分,即设置属性。
Thymeleaf的核心功能就是通过在html标签里面追加属性。可以设置的属性非常多,详细的可以参考 Thymeleaf所有属性的还没发文档。这里我们就挑选些常用的举几个例子,其他大家可以举一反三推断出用法。
-
th:object="yyy"
将对象作为一个范围内可用的变量。一般和选择表达式*{zzz}
配合使用,选择表达式后面会讲到。 -
th:text="yyy"
这个属性可以添加到几乎所有分为头尾两部分<></>
的html标签中,如<title></title>
、<td><td/>
等。th:text="yyy"
的作用是把表达式yyy对应的值添加到标签的中间。如
<td th:text="user">用户名</td>
渲染后就是<td>user<td/>
。 -
th:value="${title}"
这个属性一般和<input />
标签搭配使用,用来设置<input />
标签的value
值。如
<input th:value="username" />
渲染后就是<input value="username" />
。
表达式
下面我们再来对这些th:xxx="yyy"
中"yyy"的部分进行讲解。这个yyy我们一般称之为表达式。
Thymeleaf里面表达式主要有以下几种。
\({yyy} 变量表达式,用来获取上下文对象里面的值(controller返回的model)。还是以上面的例子来说明,如果我想要取到page对象中的number属性,使用```\){page.number}```即可。

#{yyy}
消息表达式,根据消息的key来获取消息内容。一般是用来做国际化用的。
*{yyy}
选择表达式,跟变量表达式用法差不多,但变量表达式是获取上下文里的对象,选择表达式是获取一个选择的对象。
选择表达式一般和th:object=
标签配合使用,还是以上面的例子来说明。
先用th:object="${user}"
选择了上下文中的user对象,下面想使用user对象的username属性时,直接使用*{username}
就可以了。
你可能想要问,我直接使用\({user.username}不是一样可以找到user对象的username属性么,为什么还要再搞个选择表达式?
因为```\){user.username}是先从下上文找到user,对象,再从user对象里找到username属性;而
*{username}```是直接从user对象里找到username属性。当需要从一个对象里获取很多属性的时候,使用选择表达式可以提高效率。

@{yyy}
链接表达式 设置超链接时用的表达式,一般和th:action
、th:href
配合使用
yyy
文字。可以为字符串、数字、布尔、null。如<td th:text="user">
用户名渲染后为<td>user</td>
。
_ 无操作。下划线是thymeleaf表达式的特殊字符,如果表达式就一个下划线,则什么也不做。例如<td th:text="_">
用户名渲染后依然是<td>用户名</td>
。
迭代器
我们在渲染页面时,经常需要对一个list进行循环处理,最典型的场景就是使用表格展示多条数据。这时,就需要使用到thymeleaf的迭代器th:each
。
<tr th:each="user : ${users}">
<td th:text="${user.id}">id</td>
<td th:text="${user.username}">用户名</td>
</tr>
在这个例子中,users是一个list,通过迭代器th:each对其进行遍历,每次迭代获取到的对象为user。在th:each
属性的对应的标签之间<tr th:each="user : ${users}">...</tr>
,为user对象的有效范围。
有时候,我们还想要知道迭代器的一些状态属性,如总数,当前索引等。可以通过如下方法获取。
<tr th:each="user,stat : ${users}">
<td th:text="${stat.index}">index</td>
<td th:text="${user.id}">id</td>
<td th:text="${user.username}">用户名</td>
</tr>
th:each=""
的第二个变量stat,就是迭代器的状态变量,从这个状态变量里面可以获取到很多我们想要的属性,主要有下面这些。
stat.index
当前对象在list中的索引。从0开始。
stat.count
和index差不多,也是当前对象在list中的索引,不过是从1开始。
stat.size
迭代器中元素的总数。
stat.current
当前迭代的对象。
stat.even
当前迭代的索引是否是奇数,索引指stat.index
stat.odd
当前迭代的索引是否是偶数,索引指stat.index
stat.first
当前迭代的对象是否是迭代器中的第一个。
stat.last
当前迭代的对象是否是迭代器中的最后一个。
条件语句
th:if="boolean"
th:if
的表达式需为boolean值。如果为true,则标签显示,如果为false,则标签不显示。
th:unless="boolean"
th:unless
和th:if
相反,表达式也需为boolean值。如果为true,则标签不显示,如果为false,则标签显示。
<span th:if="${stat.odd}">偶</span>
<span th:unless="${stat.odd}">奇</span>

th:swtich
一般和 th:case
结合使用 。和java语言中的swtich case语法用法类似。
<td th:switch="${user.enabled}">
<span th:case="true">可用</span><span th:case="false">不可用</span>
</td>

工具类
Thymeleaf提供了一些工具类,这里举个简单的例子展示下用法,其他详细的可以查看Thymeleaf工具类官方文档。Thymeleaf提供了一些工具类,这里举个简单的例子展示下用法,其他详细的可以查看Thymeleaf工具类官方文档。
#lists
数组工具类
总共有<span th:text="${#lists.size(page.content)}">1</span>条记录

【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· .NET Core 托管堆内存泄露/CPU异常的常见思路
· PostgreSQL 和 SQL Server 在统计信息维护中的关键差异
· C++代码改造为UTF-8编码问题的总结
· DeepSeek 解答了困扰我五年的技术问题
· 为什么说在企业级应用开发中,后端往往是效率杀手?
· 清华大学推出第四讲使用 DeepSeek + DeepResearch 让科研像聊天一样简单!
· 推荐几款开源且免费的 .NET MAUI 组件库
· 实操Deepseek接入个人知识库
· 易语言 —— 开山篇
· Trae初体验