准备
- 从Maven引入
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
- application.yml/properties配置
实际上
org.springframework.boot.autoconfigure.thymeleaf.ThymeleafProperties已经有默认的配置项,例如:
private static final Charset DEFAULT_ENCODING = StandardCharsets.UTF_8;
public static final String DEFAULT_PREFIX = "classpath:/templates/";
public static final String DEFAULT_SUFFIX = ".html";
所以可以直接使用,暂时不用关心ThymeleafProperties中的配置。
-
html文件位置及命名空间 -
要使用
Thymeleaf功能的html文件,都得放到如下所示templates目录下,刚才已经提到了Thymeleaf的一些默认配置,所以,也没必要去改变DEFAULT_PREFIX。
// org.springframework.boot.autoconfigure.thymeleaf.ThymeleafProperties
public static final String DEFAULT_PREFIX = "classpath:/templates/";
+---main
| +---java
| | \---com
| | \---xxx 包
| \---resources
| +---static
| \---templates
html文件的html 标签引入xmlns:th命名空间,防止IDE报错缺少名称空间定义,同时也有了提示,比如使用 IDEA .
<!DOCTYPE html>
<html lang="en" xmlns:th="https://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge,chrome=1">
<title>Document</title>
</head>
先了解一下简单的表达式
- 简单表达式
- 变量表达式: ${...}
- 选择变量表达式: *{...}
- 消息表达: #{...}
- 链接URL表达式: @{...}
- 片段表达式: ~{...}
以下使用org.springframework.ui.Model来传递数据
文本
标签本身没有value属性的,如p li span等用th:text渲染,有value属性则用th:value渲染
判断
@GetMapping("judge")
public String books(Model model) {
model.addAttribute("param", "xxx");
return "/books";
}
<!-- 使用 th:if -->
<div th:if="${param}">
...
</div>
当是变量是以下情况时th:if判断为false,从而不渲染元素
- 变量不存在
- 值为
null - 值为
Boolean类型的false
循环
- 简单循环
@GetMapping("books")
public String books(Model model) {
List<String> list = Arrays.asList("陸小鳳傳奇", "蘇菲的世界", "毛澤東選集");
model.addAttribute("books", list);
return "/books";
}
<ul>
<li th:each="book :${books}">
<span th:text="${book}"></span>
</li>
</ul>
- 对象集合
@Getter
@Setter
@AllArgsConstructor
public class UserObj {
private Integer id;
private String name;
private Integer age;
}
@GetMapping("users")
public String users(Model model) {
UserObj lily = new UserObj(1, "Lily", 22);
UserObj jasmine = new UserObj(2, "Jasmine", 18);
UserObj poppy = new UserObj(3, "Poppy", 6);
List<UserObj> list = Arrays.asList(lily, jasmine, poppy);
// model.addAllAttributes(list);
model.addAttribute("users", list);
return "/user";
}
<table th:if="${users}">
<thead>
<tr>
<th>ID</th>
<th>NAME</th>
<th>AGE</th>
</tr>
</thead>
<tbody>
<tr th:each="user,iterStat :${users}" th:class="${iterStat.odd}? 'odd'">
<td th:text="${user.id}"></td>
<td th:text="${user.name}"></td>
<td th:text="${user.age}"></td>
</tr>
</tbody>
</table>
第二个参数 iterStat 是一个对象,是为Thymeleaf提供了一种有助于跟踪迭代状态的机制,其拥有以下属性:
{
index: 0 索引 从零开始,
count: 从一开始的索引,
size: 数据总数,
current:com.xxx.UserObj@7684eac 当前循环的对象,
even/odd:布尔属性,当前迭代是偶数还是奇数
first: 布尔属性 是否是第一个
last: 布尔属性 是否为最后一个
}
注释
<!-- 普通html注释 -->
<!--/* 被Thymeleaf解析后不显示 */-->
<!--/*/
<div th:text="${...}">
静态打开时不显示,被Thymeleaf解析后显示
</div>
/*/-->
模板
例如页脚,页眉,菜单等部分做成模板以嵌入到其它页面中。
制作
例如制作一个header模板,在/layout目录下新建一个header.html,文件内容如下所示,因为这只是一个嵌入到其它html的片段,所以不再写<!DOCTYPE html>和其它用不到的标签。
<header xmlns:th="https://www.thymeleaf.org" th:fragment="header">
...
</header>
或者 使用id来声明
<header xmlns:th="https://www.thymeleaf.org" id="header">
...
</header>
使用
<!DOCTYPE html>
<html lang="en" xmlns:th="https://www.thymeleaf.org">
<head>
...
</head>
<body>
<div th:replace="~{/layout/header :: header}"></div>
<!-- 如果使用id声明,则加个#号 -->
<div th:replace="~{/layout/header :: #header}"></div>
</body>
</html>
差异
th:insert th:replace 和th:include之间的差异
3.0 不推荐
th:replace❓
以上面的使用为例
th:insert最简单:它将简单地将指定的片段作为子标签插入,即
<div>
<header>
...
</header>
</div>
th:replace实际上将其标签替换为引用的片段,,即
<header>
...
</header>
th:include与相似th:insert,但不插入片段,而是仅插入该片段的内容,即
<div>
...
</div>
附录
表达式基本对象
未完待续?