Thymeleaf 简介

Thymeleaf 是一个流行的模板引擎,该模板引擎采用 Java 语言开发 模板引擎是一个技术名词,是跨领域跨平台的概念,在 Java 语言体系下有模板引擎, 在 C#、 PHP 语言体系下也有模板引擎,甚至在 JavaScript 中也会用到模板引擎技术, Java 生 态下的模板引擎有 Thymeleaf 、 Freemaker、 Velocity、 Beetl(国产) 等。 Thymeleaf 对网络环境不存在严格的要求,既能用于 Web 环境下,也能用于非 Web 环 境下。在非 Web 环境下,他能直接显示模板上的静态数据;在 Web 环境下,它能像 Jsp 一 样从后台接收数据并替换掉模板上的静态数据。它是基于 HTML 的,以 HTML 标签为载体, Thymeleaf 要寄托在 HTML 标签下实现。 SpringBoot 集成了 Thymeleaf 模板技术,并且 Spring Boot 官方也推荐使用 Thymeleaf 来 替代 JSP 技术, Thymeleaf 是另外的一种模板技术,它本身并不属于 Spring Boot, Spring Boot 只是很好地集成这种模板技术,作为前端页面的数据展示, 在过去的 Java Web 开发中,我 们往往会选择使用 Jsp 去完成页面的动态渲染, 但是 jsp 需要翻译编译运行,效率低 。

Thymeleaf 的官方网站: http://www.thymeleaf.org

Thymeleaf 官方手册: https://www.thymeleaf.org/doc/tutorials/3.0/usingthymeleaf.html

SpringBoot集成Thymeleaf

在pom文件添加Thymeleaf的依赖

1
2
3
4
5
6
7
8
9
10
<!--SpringBoot 集成 Thymeleaf 的起步依赖-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<!--SpringBoot 开发 web 项目的起步依赖-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>

添加Thymeleaf的配置

1
2
3
4
5
6
7
#thymeleaf 页面的缓存开关,默认 true 开启缓存
#建议在开发阶段关闭 thymeleaf 页面缓存,目的实时看到页面
spring.thymeleaf.cache=false
#thymeleaf 模版前缀,默认可以不写
spring.thymeleaf.prefix=classpath:/templates/
#thymeleaf 模版后缀,默认可以不写
spring.thymeleaf.suffix=.html

创建控制器,返回html视图的名称

1
2
3
4
5
6
7
8
@Controller
public class ThymeleafController {
@RequestMapping(value = "/index")
public String index(Model model) {
model.addAttribute("data","SpringBoot 成功集成 Thymeleaf 模版! ");
return "index";
}
}

展示数据

在 src/main/resources 的 templates 下建一个 index.html 页面用于

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>SpringBoot 集成 Thymeleaf</title>
</head>
<body >
<!--Thymeleaf 前端框架以 Html 为载体-->
<span th:text="${data}"></span>
<p th:text="${data}"></p>
<div th:text="${data}"></div>
</body>
</html>
注 意 :Springboot使用thymeleaf作为视图展示,
约定将模板文件放置在src/main/resource/templates 目录下,
静态资源放置在 src/main/resource/static 目录下

Thymeleaf的基本内容

标准变量表达式

注意: th:text=”” 是 Thymeleaf 的一个属性,用于文本的显示

1
2
语法 ${}
说明 标准变量表达式用于访问容器( tomcat)上下文环境中的变量,功能和 EL 中的 ${} 相 同。 Thymeleaf 中的变量表达式使用 {变量名} 的方式获取 Controller 中 model 其中的数据

选择变量表达式

1
2
3
4
5
6
语法: *{...}
说明
选择变量表达式,也叫星号变量表达式,使用 th:object 属性来绑定对象
选择表达式首先使用 th:object 来绑定后台传来的 User 对象,然后使用 * 来代表这个对象,后面 {} 中的值是此对象中的属性。
选择变量表达式 *{...} 是另一种类似于标准变量表达式 ${...} 表示变量的方法
选择变量表达式在执行时是在选择的对象上求解,而${...}是在上下文的变量 Model 上求解,这种写法比标准变量表达式繁琐,了解即可
1
2
3
4
5
6
7
8
<h2>展示 User 用户信息(星号表达式,仅在 div 范围内有效): </h2>

<div th:object="${user}">
用户编号: <span th:text="*{id}"></span><br/>
用户姓名: <span th:text="*{name}"></span><br/>
用户手机号: <span th:text="*{phone}"></span><br/>
用户地址: <span th:text="*{address}"></span><br/>
</div>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
<h2>标准变量表达式和选择变量表达式混用</h2>
<h3>=======标准变量表达式=======</h3>
用户编号: <span th:text="${user.id}"></span><br/>
用户姓名: <span th:text="${user.name}"></span><br/>
用户手机号: <span th:text="${user.phone}"></span><br/>
用户地址: <span th:text="${user.address}"></span><br/>


<h3>=======选择变量表达式=======</h3>
用户编号: *{user.id} ==> <span th:text="*{user.id}"></span><br/>
用户姓名: *{ user.name} ==> <span th:text="*{user.name}"></span><br/>
用户手机号: *{user.phone} ==> <span th:text="*{user.phone}"></span><br/>
用户地址: *{user.address} ==> <span
th:text="*{user.address}"></span><br/>

内嵌表达式

  • 文本内联
    [[…]]之间的表达式在Thymeleaf被认为是内联表达式,在其中您可以使用任何类型的表达式,也会有效th:text属性。
    1
    2
    3
    <p>Hello, [[${session.user.name}]]!</p>
    <!-- 等同于 -->
    <p>Hello, <span th:text="${session.user.name}">Sebastian</span>!</p>
  • 脚本内联
    Thymeleaf提供一系列的“脚本”的内联模式功能,这样你就可以将你的数据在脚本中创建一些脚本语言。
    1
    2
    3
    4
    5
    6
    7
    8
    9
    <script th:inline="javascript">
    var user = [[${user.username}]];
    alert(user);
    </script>

    <script th:inline="javascript">
    var msg = 'Hello, ' + [[${user.username}]];
    alert(msg);
    </script>

th:inline

  1. 内联text: 在html标签外,获取表达式的值

    语法:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    <p>显示姓名是:[[${key}]]</p>

    <div style="margin-left: 400px">
    <h3>内联 text, 使用内联表达式显示变量的值</h3>
    <div th:inline="text">
    <p>我是[[${name}]],年龄是[[${age}]]</p>
    我是<span th:text="${name}"></span>,年龄是<span th:text="${age}"></span>
    </div>

    <div>
    <p>使用内联text</p>
    <p>我是[[${name}]],性别是[[${sex}]]</p>
    </div>
    </div>
  1. 内联javascript
1
2
3
4
5
6
7
8
9
10
11
例子:
<script type="text/javascript" th:inline="javascript">
var myname = [[${name}]];
var myage = [[${age}]];

//alert("获取的模板中数据 "+ myname + ","+myage)

function fun(){
alert("单击事件,获取数据 "+ myname + ","+ [[${sex}]])
}
</script>

URL表达式

语法:@{}

主要用于链接、地址的展示, 可用于 <script src="..."><link href="..."><a href="..."><form action="..."><img src="">等,可以 在 URL 路径中动态获取数据

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<body>
<h1>URL 路径表达式: @{...}</h1>
<h2>绝对路径(没有参数) </h2>
<a th:href="@{http://localhost:8080/thymeleaf/info}">查看:绝对路径</a>

<h2>绝对路径(路径中有参数) </h2>
<a th:href="@{'http://localhost:8080/thymeleaf/user/info?id=' +
${user.id}}">查看用户信息:绝对路径(带参数)</a>

<h2 style="color: red">实际开发推荐使用:相对路径(没有参数) </h2>
<a th:href="@{/thymeleaf/info}">查看:相对路径</a>

<h2 style="color: red">实际开发推荐使用:相对路径(路径中有参数) </h2>
<a th:href="@{'/thymeleaf/user/info?id=' + ${user.id}}">查看用户信息:相
对路径(带参数) </a>
<a th:href="@{/thymeleaf/info(id=${user.id})}">推荐使用:优雅的带参数路径
写法</a>
</body>

th:action

th:action 定义后台控制器的路径,类似

标签的 action 属性,主要结合 URL 表达式,获 取动态变量

1
2
3
4
5
6
<h1>th:action 属性的使用</h1>
<h2>请求路径中需要动态获取变量数据时,必须添加 th 前缀</h2>
<form th:action="@{'/user/login?id='+${user.id}}"></form>
<h2>以下两种方式获取不到用户 id</h2>
<form action="'/user/login?id='+${user.id}"></form>
<form action="/user/login"+${user.id}></form>
1
2
3
4
5
6
思考:为什么后两个中${user.id} 获取不到数据?
因为我们 Thymeleaf 是以 html 为载体的,所以 html 不会认识${}语法。
我们请求的流程是,发送请求给服务器,服务器接收请求后,处理请求,跳转到指定的静
态 html 页面,在服务器端, Thymeleaf 模板引擎会按照它的语法,对动态数据进行处理,
所以如果要是 th 开头,模板引擎能够识别,会在服务器端进行处理,获取数据;如果没有
以 th 开头,那么 Thymeleaf 模板引擎不会处理,直接返回给客户端了。

th:method

设置请求方法

1
2
3
<form id="login" th:action="@{/login}" th:method="post">......</form>
<h1>th:method 属性的使用</h1>
<form th:action="@{/user/login}" th:method="post"></form>

th:src

th:src 用于外部资源引入

比如<script>标签的 src 属性, <img>标签的 src 属性,常与@{}表达式结 合使用,在 SpringBoot 项目的静态资源都放到 resources 的 static 目录下。 放到 static 路径下的内容,写路径时不需要写上 static

1
2
3
4
5
6
7
8
9
10
11
<h1>th:src 属性的使用</h1>
<!--以下方式无法引入 js-->
<script src="/static/js/jquery-1.7.2.min.js"></script>

<!--该方法是常用方法-->
<script type="text/javascript" th:src="@{/jquery-1.7.2.min.js}"></script>
<script>
$(function () {
alert("引入 js 文件");
});
</script>

这种方式比传统方式的好处是,在 URL 表达式前加/,会自动加上上下文根,避免 404 找不 到资源的情况

th:id

th:id 类似 html 标签中的 id 属性

1
<span th:id="${hello}">aaa</span>

th:name

th:name 设置名称

1
<input th:type="text" th:id="userName" th:name="userName">

th:value

th:value 类似 html 标签中的 value 属性,能对某元素的 value 属性进行赋值

1
<input type="hidden" id="userId" name="userId" th:value="${userId}">

th:attr

th:attr 该属性也是用于给 HTML 中某元素的某属性赋值,好处是可以给 html 中没有定义的属性动 态的赋值

1
2
3
4
<h1>th:attr 属性的使用</h1>
<span zhangsan="${user.name}"></span>
<!--通过 th:attr 对自定义的属性赋值-->
<span th:attr="zhangsan=${user.name}"></span>

th:text

th:text 用于文本的显示,该属性显示的文本在标签体中,如果是文本框,数据会在文本框外显示, 要想显示在文本框内,使用th:value

1
<input type="text" id="realName" name="reaName" th:text="${realName}">

th:object

th:object 用于数据对象绑定 通常用于选择变量表达式(星号表达式)

th:onclick

1
2
3
4
5
6
7
8
<h1>th:onclick 的使用</h1>
<!--目前 thymeleaf 版本要求只能传递数字和布尔值-->
<a th:onclick="'show('+${user.id}+')'">点击:显示学生编号</a>
<script type="text/javascript">
function show(id) {
alert("用户编号为: " + id);
}
</script>

th:style

th:style 设置样式

1
2
<a th:onclick="'show('+${user.id}+')'"
th:style="'font-size:40px;color:red;'">点击:显示学生编号</a>

th:each

比如从后台传来一个对象集合那么就可以使用此属性遍历输出,它与 JSTL 中的<c: forEach>类似,此属性既可以循环遍历集合,也可以循环遍历数组及 Map

1
2
3
th:each
这个属性非常常用,比如从后台传来一个对象集合那么就可以使用此属性遍历输出,它与
JSTL 中的<c: forEach>类似,此属性既可以循环遍历集合,也可以循环遍历数组及 Map
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<body>
<h1>th:each 循环遍历 List 集合</h1>
<div style="color: red">
1.user:当前对象的变量名<br/>
2.userStat:当前对象的状态变量名<br/>
3.${userList}:循环遍历的集合<br/>
4.变量名自定义
</div>

<div th:each="user,userStat:${userList}">
<span th:text="${userStat.index}"></span>
<span th:text="${user.id}"></span>
<span th:text="${user.name}"></span>
<span th:text="${user.phone}"></span>
<span th:text="${user.address}"></span>
</div>
</body>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
th:each="user, iterStat : ${userlist}"中的 ${userList} 是后台传过来的集合
◼ user
定义变量,去接收遍历${userList}集合中的一个数据
◼ iterStat
${userList} 循环体的信息
◼ 其中 user 及 iterStat 自己可以随便取名
◼ interStat 是循环体的信息,通过该变量可以获取如下信息
index: 当前迭代对象的 index(从 0 开始计算)
count: 当前迭代对象的个数(从 1 开始计算) 这两个用的较多
size: 被迭代对象的大小
current: 当前迭代变量
even/odd: 布尔值,当前循环是否是偶数/奇数(从 0 开始计算)
first: 布尔值,当前循环是否是第一个
last: 布尔值,当前循环是否是最后一个
注意:循环体信息 interStat 也可以不定义,则默认采用迭代变量加上 Stat 后缀,即 userStat
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<head>
<meta charset="UTF-8">
<title>循环遍历 Map 集合</title>
</head>
<body>
<h1>th:each 循环遍历 Map 集合</h1>
<div th:each="userMap,userMapStat:${userMaps}">
<span th:text="${userMapStat.count}"></span>
<span th:text="${userMap.key}"></span>
<span th:text="${userMap.value.id}"></span>
<span th:text="${userMap.value.name}"></span>
<span th:text="${userMap.value.phone}"></span>
<span th:text="${userMap.value.address}"></span>
</div>
<span th:text="${userMap.value.id}"></span>
<span th:text="${userMap.value.name}"></span>
<span th:text="${userMap.value.phone}"></span>
<span th:text="${userMap.value.address}"></span>
</div>

遍历 Array 数组, 在 ThymeleafController 中的 eachArray 方法中准备数组数据

1
2
3
4
5
6
7
8
9
10
11
12
13
<head>
<meta charset="UTF-8">
<title>循环遍历 Array 数组</title>
</head>
<body>
<div th:each="user,userStat:${userArray}">
<span th:text="${userStat.count}"></span>
<span th:text="${user.id}"></span>
<span th:text="${user.name}"></span>
<span th:text="${user.phone}"></span>
<span th:text="${user.address}"></span>
</div>
</body>

th:if 与 th:unless

条件判断

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
<h1>th:if 用法:如果满足条件显示,否则相反</h1>
<div th:if="${sex eq 1}">
男: <input type="radio" name="sex" th:value="1"/>
</div>
<div th:if="${sex eq 0}">
女: <input type="radio" name="sex" th:value="0"/>
</div>
<h1>th:unless 用法:与 th:if 用法相反,即对条件判断条件取反</h1>
<div th:unless="${sex == 1}">
男: <input type="radio" name="sex" th:value="1"/>
</div>
<div th:unless="${sex eq 0}">
女: <input type="radio" name="sex" th:value="0"/>
</div>
<div th:if="${user1 eq null}">
<h3 style="color: red">用户未登录</h3>
</div>
<div th:unless="${user2 == null}">
用户姓名: <span th:text="${user2.name}"></span>
</div>
<h1>从 session 中获取值</h1>
<div th:if="${user3 != null}">
<span th:text="${user3.name}"></span>
</div>
</body>

th:switch 与 th:case

1
2
3
4
5
6
<h1>th:switch/th:case 用法</h1>
<div th:switch="${sex}">
<span th:case="1">性别:男</span><br/>
<span th:case="2">性别:女</span><br/>
<span th:case="*">性别:保密</span>
</div>

一旦某个 case 判断值为 true,剩余的 case 默认不执行,"*"表示默 认的 case,前面的 case 都不匹配时候,执行默认的 case

文本字面量

用单引号’…’包围的字符串为文本字面量

1
2
3
<h1>文本字面量:用单引号'...'包围的字符串</h1>
<a th:href="@{'/user/info?id=' + ${user.id}}">查看用户:文本字面的路径使用</a><br/>
<span th:text="您好"></span>

数字字面量

1
2
3
<h1>数字字面量</h1>
今年是<span th:text="2019">1949</span><br/>
20 年后,将是<span th:text="2019 + 20">1969</span><br/>

boolean 字面量

1
2
3
<h1>boolean 字面量</h1>
<div th:if="${success}">执行成功</div>
<div th:unless="${flag}">执行不成功</div>

null 字面量

1
2
3
<h1>null 字面量</h1>
<span th:if="${user ne null}">用户不为空</span><br/>
<span th:unless="${user eq null}">用户不为空(使用 th:unless 取反) </span><br/>

Thymeleaf 字符串拼接

1
2
3
4
5
<h1>文本字面量使用"+"拼接字符串</h1>
<span th:text="'共'+${totalRows}+'条'+${totalPage}+'页,当前第'+${currentPage}+'
页'"></span>
<h1>另一种更优雅的方式:使用"|要拼接的内容|"减少字符串拼接的加号</h1>
<span th:text="|共${totalRows}条${totalPage}页,当前第${currentPage}页|"></span>

Thymeleaf 运算符

1
2
3
4
三元运算:表达式?”正确结果”:”错误结果”
算术运算: + , - , * , / , %
关系比较:: > , < , >= , <= ( gt , lt , ge , le )
相等判断: == , != ( eq , ne )

Thymaleaf 表达式基本对象

模板引擎提供了一组内置的对象,这些内置的对象可以直接在模板中使用,这些对象由 #号开始引用,我们比较常用的内置对象

1
2
3
#request
#request 相 当 于 httpServletRequest 对 象 , 这 是 3.x 版 本 , 若 是 2.x 版 本 使 用
#httpServletRequest,在页面获取应用的上下文根,一般在 js 中请求路径中加上可以避免 404
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>Thymeleaf 表达式基本对象</title>
</head>
<body>
<script type="text/javascript" th:inline="javascript">

var basePath = [[${#httpServletRequest.getScheme() + "://" +
#httpServletRequest.getServerName() + ":" +
#httpServletRequest.getServerPort() +
#httpServletRequest.getContextPath()}]];
//http://localhost:8080/springboot/user/login
//获取协议名称
var scheme = [[${#request.getScheme()}]];
//获取服务 IP 地址
var serverName = [[${#request.getServerName()}]];
//获取服务端口号
var serverPort = [[${#request.getServerPort()}]];
//获取上下文根
var contextPath = [[${#request.getContextPath()}]];

var allPath = scheme+"://"+serverName+":"+serverPort+contextPath;
alert(allPath)
1
2
3
#session
相当于 HttpSession 对象,这是 3.x 版本,若是 2.x 版本使用#httpSession
在后台方法中向 session 中放数据
1
2
3
<h1>从 SESSION 中获取用户名称</h1>
<span th:text="${#session.getAttribute('username')}"></span><br/>
<span th:text="${#httpSession.getAttribute('username')}"></span>

Thymeleaf 表达式功能对象

模板引擎提供的一组功能性内置对象,可以在模板中直接使用这些对象提供的功能方法 工作中常使用的数据类型,如集合,时间,数值,可以使用 Thymeleaf 的提供的功能性对象 来处理它们

1
2
3
4
5
6
7
8
9
10
11
12
13
14
内置功能对象前都需要加#号,内置对象一般都以 s 结尾
官方手册: http://www.thymeleaf.org/doc/tutorials/3.0/usingthymeleaf.html
#dates: java.util.Date 对象的实用方法:
<span th:text="${#dates.format(curDate, 'yyyy-MM-dd HH:mm:ss')}"></span>
#calendars: 和 dates 类似, 但是 java.util.Calendar 对象;
#numbers: 格式化数字对象的实用方法;
#strings: 字符串对象的实用方法: contains, startsWith, prepending/appending 等;
#objects: 对 objects 操作的实用方法;
#bools: 对布尔值求值的实用方法;
#arrays: 数组的实用方法;
#lists: list 的实用方法,比如<span th:text="${#lists.size(datas)}"></span>
#sets: set 的实用方法;
#maps: map 的实用方法;
#aggregates: 对数组或集合创建聚合的实用方法;