開發(fā)環(huán)境
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.1.0.RELEASE</version>
</parent>
<properties>
<java.version>1.8</java.version>
</properties>
引入依賴
主要增加 spring-boot-starter-thymeleaf 依賴:
-
spring-boot-starter-thymeleaf:自動(dòng)裝配 Thymeleaf 模板引擎
<dependencies>
...
<!-- Thymeleaf Start -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<!-- Thymeleaf End -->
...
</dependencies>
配置 Thymeleaf
application.yml
spring:
thymeleaf:
cache: false # 是否開啟模板緩存,默認(rèn)為:true,開發(fā)時(shí)關(guān)閉緩存,不然沒法看到實(shí)時(shí)頁(yè)面!
mode: HTML # 指定模板的模式,默認(rèn)為:HTML
encoding: UTF-8 # 指定模板的編碼,默認(rèn)為:UTF-8
prefix: classpath:/templates/ # 指定模板的前綴,默認(rèn)為:classpath:/templates/
suffix: .html # 指定模板的后綴,默認(rèn)為:.html
servlet:
content-type: text/html # 指定 Content-Type 值,默認(rèn)為:text/html
從 org.thymeleaf.templatemode.TemplateMode 中可見 Thymeleaf 從 3.0.0 版本開始使用 HTML 替代 HTML5、LEGACYHTML5、XHTML、VALIDXHTML。如果還在使用 3.0.0 以前的版本,想要使用非嚴(yán)格的 HTML,需要做以下配置:
- 在
pom.xml中引入nekohtml依賴 - 在
application.yml中配置spring.thymeleaf.mode=LEGACYHTML5
更多屬性配置請(qǐng)參考「Appendix A. Common application properties」中 # THYMELEAF (ThymeleafAutoConfiguration) 模塊的屬性介紹。(TIPS:使用 CTRL + F 進(jìn)行快速定位)
創(chuàng)建測(cè)試 Controller
創(chuàng)建一個(gè) Controller,為 message 屬性賦值并設(shè)置跳轉(zhuǎn),代碼如下:
IndexController.java
@Controller
public class IndexController {
@GetMapping(path = {"/", "index"})
public String indexPage(Model model) {
model.addAttribute("message", "Hello Thymeleaf!");
return "index";
}
}
創(chuàng)建測(cè)試 HTML 頁(yè)面
在 templates 目錄下創(chuàng)建 index.html 文件,并在 html 標(biāo)簽中聲明 Thymeleaf 命名空間 xmlns:th="http://www.thymeleaf.org",代碼如下:
index.html
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8"/>
<title>Thymeleaf</title>
</head>
<body>
<h1 th:text="${message}">Hello World!</h1>
</body>
</html>
其中關(guān)鍵的代碼是:
xmlns:th="http://www.thymeleaf.org"
主要是讓 IDE 識(shí)別 Thymeleaf 命名空間,這樣在標(biāo)簽里輸入 th: 后,IDE 會(huì)提示相應(yīng)的語(yǔ)法,方便開發(fā)!不加入這句代碼也不會(huì)影響 Thymeleaf 模板引擎的渲染,以及頁(yè)面的正常顯示。
測(cè)試訪問
啟動(dòng)成功后,訪問 http://127.0.0.1:8080,即可看到效果:

訪問結(jié)果:Hello Thymeleaf!
Thymeleaf 常用語(yǔ)法
- JAVA 源碼路徑:TagsController.java
- HTML 源碼路徑:
templates目錄
獲取變量值
<p th:text="'Hello! ' + ${name} + '!'" >name</p>
可以看出獲取變量值用 $ 符號(hào),對(duì)于 JavaBean 的話使用 變量名.屬性名 方式獲取,這點(diǎn)和 EL 表達(dá)式一樣。
另外 $ 表達(dá)式只能寫在 th 標(biāo)簽內(nèi)部,不然不會(huì)生效,上面例子就是使用 th:text 標(biāo)簽的值替換 <p>...</p> 標(biāo)簽里面的值,至于 p 里面的原有的值只是為了給前端開發(fā)時(shí)做展示用的。這樣的話很好的做到了前后端分離。
內(nèi)容信息輸出:th:text 與 th:utext
-
th:text:以純文本的方式輸出 -
th:utext:以 HTML 標(biāo)簽的方式輸出,瀏覽器能正常渲染

HTML 代碼:
<body>
<h2 th:text="' th:text   ? ' + ${content}">以純文本的方式輸出</h2>
<h2 th:utext="'th:utext ? ' + ${content}">以 HTML 標(biāo)簽的方式輸出,瀏覽器能正常渲染</h2>
</body>
JAVA 代碼:
@GetMapping("/text-utext")
public String textAndutext(Model model) {
model.addAttribute("content", "<span style='color:red'>thymeleaf text output</span>");
return "text-utext";
}
引用 URL
對(duì)于 URL 的處理是通過語(yǔ)法 @{…} 來(lái)處理的:

HTML 代碼:
<body>
<ul>
<li>
<a th:href="@{https://github.com/{username}(username=${username})}">絕對(duì)路徑 1</a>,
<a th:href="@{https://www.baidu.com}">絕對(duì)路徑 2</a>
</li>
<li>
<a th:href="@{/}">相對(duì)路徑</a>
</li>
<li>
<a th:href="@{/css/app.css}">Content 路徑,默認(rèn)訪問 static 下的 CSS 文件</a>
</li>
</ul>
</body>
JAVA 代碼:
@GetMapping("/refer-url")
public String referUrl(Model model) {
model.addAttribute("username", "y0ngb1n");
return "refer-url";
}
類似的標(biāo)簽有:th:href 和 th:src
字符串替換
很多時(shí)候可能我們只需要對(duì)一大段文字中的某一處地方進(jìn)行替換,可以通過字符串拼接操作完成:
<p th:text="'Welcome to our application, ' + ${user.name} + '!'">
可以用另一種更簡(jiǎn)潔的方式:
<p th:text="|Welcome to our application, ${user.name}!|">
文字替換本身可以和與其他表達(dá)式聯(lián)合使用:
<p th:text="${onevar} + ', ' + |${twovar}, ${threevar}|">
當(dāng)然這種形式限制比較多,|…| 中只能包含變量表達(dá)式 ${…},不能包含其他常量、條件表達(dá)式等。

HTML 代碼:
<body>
<p th:text="'Welcome to our application, ' + ${user.name} + '!'">
<p th:text="|Welcome to our application, ${user.name}!|">
<p th:text="${onevar} + ', ' + |${twovar}, ${threevar}|">
</body>
JAVA 代碼:
@GetMapping("replace-text")
public String replaceText(Model model) {
model.addAttribute("user", user);
model.addAttribute("onevar", "one");
model.addAttribute("twovar", "two");
model.addAttribute("threevar", "three");
return "replace-text";
}
運(yùn)算符
在表達(dá)式中可以使用各類算術(shù)運(yùn)算符,例如 +, -, *, /, %:
th:with="isEven=(${user.age} % 2 == 0)"
邏輯運(yùn)算符 >, <, <=, >=, ==, != 都可以使用,唯一需要注意的是使用 <, > 時(shí)需要用它的 HTML 轉(zhuǎn)義符:
th:if="${user.age} > 1"
th:text="'Environment is ' + ((${env} == 'dev') ? 'Development' : 'Production')"

HTML 代碼:
<body>
<h2 th:text="|name: ${user.name}, age: ${user.age}, env: ${env}|"></h2>
<p th:with="isEven=(${user.age} % 2 == 0)">年齡為偶數(shù)</p>
<p th:with="isEven=(${user.age == 18})">喲,才 18 吶!</p>
<p th:if="${user.age} > 18">當(dāng)前年齡大于 18</p>
<div th:class="${env} == 'dev' ? 'dev' : 'prod'"></div>
<p th:text="'當(dāng)前環(huán)境:' + ((${env} == 'dev') ? 'Development' : 'Production')"></p>
</body>
JAVA 代碼:
@GetMapping("/operator")
public String operator(Model model) {
model.addAttribute("user", user);
model.addAttribute("env", "dev");
return "operator";
}
條件判斷
th:if, th:unless
使用 th:if 和 th:unless 屬性進(jìn)行條件判斷,下面的例子中,標(biāo)簽只有在 th:if 中條件成立時(shí)才顯示:
<a th:href="@{/login}" th:if=${user == null}>Login</a>
<a th:href="@{/login}" th:unless=${user != null}>Login</a>
th:unless 于 th:if 恰好相反,只有表達(dá)式中的條件不成立,才會(huì)顯示其內(nèi)容。
th:switch, th:case
支持多路選擇 Switch 結(jié)構(gòu):
<div th:switch="${user.role}">
<p th:case="'admin'">User is an administrator</p>
<p th:case="#{roles.manager}">User is a manager</p>
</div>
默認(rèn)屬性 default 可以用 * 表示:
<div th:switch="${user.role}">
<p th:case="'admin'">User is an administrator</p>
<p th:case="#{roles.manager}">User is a manager</p>
<p th:case="*">User is some other thing</p>
</div>
消息表達(dá)式:
#{...},也稱為文本外部化、國(guó)際化或 i18n

HTML 代碼:
<body>
<a th:href="@{/login}" th:unless="${user == null}">登錄</a>
<p th:if="${user != null}">歡迎,<span th:text="|${user.name}(role: ${user.role})|">tony</span></p>
<div th:switch="${user.role}">
<p th:case="'admin'">User is an administrator</p>
<p th:case="#{roles.manager}">User is a manager</p>
<p th:case="*">User is some other thing</p>
</div>
</body>
JAVA 代碼:
@GetMapping("/condition")
public String condition(Model model) {
model.addAttribute("user", user);
return "condition";
}
循環(huán)
渲染列表數(shù)據(jù)是一種非常常見的場(chǎng)景,例如現(xiàn)在有 n 條記錄需要渲染成一個(gè)表格,該數(shù)據(jù)集合必須是可以遍歷的,使用 th:each 標(biāo)簽:
HTML 代碼:
<body>
<table>
<tr>
<th>NAME</th>
<th>AGE</th>
<th>ADMIN</th>
</tr>
<tr th:each="user : ${users}">
<td th:text="${user.name}">Onions</td>
<td th:text="${user.age}">22</td>
<td th:text="${user.role} == 'admin' ? #{true} : #{false}">yes</td>
</tr>
</table>
</body>
可以看到,需要在被循環(huán)渲染的元素(這里是)中加入 th:each 標(biāo)簽,其中 th:each="prod : ${prods}" 意味著對(duì)集合變量 prods 進(jìn)行遍歷,循環(huán)變量是 prod 在循環(huán)體中可以通過表達(dá)式訪問。
JAVA 代碼:
@GetMapping("/loop")
public String loop(Model model) {
List<User> users = new ArrayList<>(3);
users.add(user);
users.add(User.builder().name("tony").age(23).role("user").build());
users.add(User.builder().name("tom").age(21).role("user").build());
model.addAttribute("users", users);
return "loop";
}

更多標(biāo)簽用法請(qǐng)參考「Thymeleaf 常用語(yǔ)法」、「Thymeleaf 參考手冊(cè)」解鎖更多技巧 ??