前言:
最近聽說thymeleaf好像也挺流行的,還說是spring官方推薦使用,那thymeleaf究竟是什么呢?spring為什么推薦用它呢?怎么用呢?本文將為你揭秘!
歡迎大家關注我的公眾號 javawebkf,目前正在慢慢地將簡書文章搬到公眾號,以后簡書和公眾號文章將同步更新,且簡書上的付費文章在公眾號上將免費。
一、thymeleaf簡介:
thymeleaf是一種Java模板引擎,那何為模板引擎呢?模板引擎就是為了使用戶頁面和業(yè)務數(shù)據(jù)相互分離而出現(xiàn)的,將從后臺返回的數(shù)據(jù)生成特定的格式的文檔,這里說的特定格式一般都指HTML文檔。它能夠處理html、xml、js、css甚至純文本,類似于freemarker。它的優(yōu)點是語法優(yōu)雅易懂、原型即頁面、遵從web標準。原型即頁面是它的特色,所謂原型即頁面,就是你寫的html,靜態(tài)的去訪問是什么樣,動態(tài)的去訪問還是這樣,只不過動態(tài)的時候會把數(shù)據(jù)填充進去。
二、thymeleaf標準方言:
1、變量表達式:${...}
例如前端接收一個user,想取出user的name屬性,就可以用變量表達式:
<span th:text="${user.name}">
2、消息表達式:#{...}
也稱為文本外部化、國際化或i18n.
<p th:text=" #{header.address.city}" >...</p>
3、選擇表達式:*{...}
與變量表達式的區(qū)別:選擇表達式是在當前選擇的對象上執(zhí)行而不是整個上下文。
<form action="/users" th:action="@{/users}" method="POST" th:object="${userModel.user}">
<input type="hidden" name="id" th:value="*{id}">
</form>
這里id就用了選擇表達式,在此處*{id}與${userModel.user.id}效果一樣。
4、鏈接表達式:@{...}
url可以是相對的,也可以是絕對的。
<a th:href="@{.../users/list}">...</a>
<a th:href="@{http://www.baidu.com}">...</a>
5、分段表達式:th:insert 、th:replace 、th:include
就相當插入。這三個的區(qū)別:
現(xiàn)有一個片段如下:
<footer th:fragment="copy">
<h1> Hello Thymeleaf </h1>
</footer>
#號分別代表insert、replace、include進行操作:
<div th:#="footer :: copy"></div>
th:insert 的結果:
<div>
<footer th:fragment="copy">
<h1> Hello Thymeleaf </h1>
</footer>
</div>
把footer標簽插入到了div標簽中。
th:replace的結果:
<footer th:fragment="copy">
<h1> Hello Thymeleaf </h1>
</footer>
把div標簽換成了footer標簽。
th:include的結果:
<div>
<h1> Hello Thymeleaf </h1>
<div>
把div標簽里面的內(nèi)容換成了footer標簽里面的內(nèi)容。3.X版本后不再推薦使用。
6、字面量:
字面量可以是文本、數(shù)字、布爾和null等類型。
7、算術操作:+、-、*、/、%
例如:
<div th:with="isEven=(${user.age} % 2 == 0)">
8、其他運算符:
比較: >、<、>=、<= (gt、lt、ge、le)
等價: ==、!= (eq、ne)
三目運算符:
<tr th:class="${row.even} ? 'even' : 'odd' "></tr>
9、迭代器:th:each
相當于Java的foreach.
<tr th:each="user : ${userList}">
<td th:text="${user.id}"></td>
<td th:text="${user.email}"></td>
</tr>
這樣就是遍歷userList集合。
迭代器的狀態(tài)變量有:
index、count、size、current、even/odd、first、last
10、條件語句:th:if、th:unless、switch
<div th:switch="${user.role}">
<p th:case=" 'admin' ">User is admin</p>
<p th:case=" 'guest' ">User is guest</p>
</div>
11、模板布局:th:fragment
比如定義一個公用的頁頭:
<div th:fragment="header">
<h1>Thymeleaf in action</h1>
<a href="/users" >首頁</a>
</div>
在其他頁面直接這樣引用就行:
<div th:replace="~{fragments/header :: header}"></div>
12、表達式基本對象:
表達式基本對象有:param、session、application、request、servletContext。
三、thymeleaf與springboot集成案例:
本案例使用gradle構建,未涉及數(shù)據(jù)庫,數(shù)據(jù)保存在ConcurrentMap中。未曾了解gradle的老鐵可以參考一下gradle的使用。點我下載本案例源碼。
項目結構如下:

1、添加依賴:
dependencies {
compile('org.springframework.boot:spring-boot-starter-web')
testCompile('org.springframework.boot:spring-boot-starter-test')
//thymeleaf的依賴
compile('org.springframework.boot:spring-boot-starter-thymeleaf')
}
2、application.properties:
#thymeleaf相關配置
spring.thymeleaf.encoding=UTF-8
spring.thymeleaf.cache=false
spring.thymeleaf.mode=HTML5
3、entity層:
public class User {
private Long id;
private String name;
private String email;
}
4、dao層:
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.atomic.AtomicLong;
import org.springframework.stereotype.Repository;
import com.zhu.test.dao.UserDao;
import com.zhu.test.entity.User;
/**
* user dao層實現(xiàn)
* @author zhu
*
*/
@Repository
public class UserDaoImpl implements UserDao {
//用來計數(shù)的
private static AtomicLong counter = new AtomicLong();
// 用來保存user的map
private final ConcurrentMap<Long, User> userMap = new ConcurrentHashMap<>();
@Override
public User saveOrUpdateUser(User user) {
Long id = user.getId();
if(id == null) {//save
id = counter.incrementAndGet();
user.setId(id);
}
this.userMap.put(id, user);
return user;
}
@Override
public void deleteUser(Long id) {
this.userMap.remove(id);
}
@Override
public User getUserById(Long id) {
return this.userMap.get(id);
}
@Override
public List<User> listUsers() {
return new ArrayList<User>(this.userMap.values());
}
}
將user保存在ConcurrentMap中,crud操作其實都是對這個map進行操作。
5、controller層:
@RestController
@RequestMapping("/users")
public class UserController {
@Autowired
private UserDao userDao;
/**
* 查詢所有用戶
*
* @param model
* @return
*/
@GetMapping
public ModelAndView list(Model model) {
model.addAttribute("userList", userDao.listUsers());
model.addAttribute("title", "用戶管理");
return new ModelAndView("user/list", "userModel", model);
}
/**
* 根據(jù)id查詢用戶
*
* @param id
* @param model
* @return
*/
@GetMapping("{id}")
public ModelAndView view(@PathVariable("id") Long id, Model model) {
User user = userDao.getUserById(id);
model.addAttribute("user", user);
model.addAttribute("title", "查看用戶");
return new ModelAndView("user/view", "userModel", model);
}
/**
* 獲取創(chuàng)建表單頁面
*
* @param model
* @return
*/
@GetMapping("/form")
public ModelAndView createForm(Model model) {
model.addAttribute("user", new User());
model.addAttribute("title", "創(chuàng)建用戶");
return new ModelAndView("user/form", "userModel", model);
}
/**
* 保存或更新用戶
*
* @param user
* @return
*/
@PostMapping
public ModelAndView saveOrUpdateUser(User user) {
user = userDao.saveOrUpdateUser(user);
return new ModelAndView("redirect:/users");
}
/**
* 刪除用戶
*
* @param id
* @return
*/
@GetMapping("/delete/{id}")
public ModelAndView delete(@PathVariable("id") Long id) {
userDao.deleteUser(id);
return new ModelAndView("redirect:/users");// 重定向到list頁面
}
/**
* 獲取修改用戶的界面
*
* @param id
* @param model
* @return
*/
@GetMapping("/modify/{id}")
public ModelAndView modify(@PathVariable("id") Long id, Model model) {
User user = userDao.getUserById(id);
model.addAttribute("user", user);
model.addAttribute("title", "修改用戶");
return new ModelAndView("user/form", "userModel", model);
}
}
6、前端頁面:
注意:要使用thymeleaf,需要在html標簽中加上
xmlns:th="http://www.thymeleaf.org"
xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout"
如下頁面:
頁頭:header.html
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org"
xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout">
<head>
<meta charset="UTF-8">
<title>thymeleaf in action</title>
</head>
<body>
<div th:fragment="header">
<h1>Thymeleaf in action</h1>
<a href="/users" >首頁</a>
</div>
</body>
</html>
頁腳:footer.html
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org"
xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout">
<head>
<meta charset="UTF-8">
<title>thymeleaf in action</title>
</head>
<body>
<div th:fragment="footer">
<a href="#" >郵箱</a>
</div>
</body>
</html>
form.html:
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org"
xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout">
<head>
<meta charset="UTF-8">
<title>thymeleaf in action</title>
</head>
<body>
<div th:replace="~{fragments/header :: header}"></div>
<h3 th:text="${userModel.title}">test</h3>
<form action="/users" th:action="@{/users}" method="POST" th:object="${userModel.user}">
<input type="hidden" name="id" th:value="*{id}">
名稱:<br>
<input type="text" name="name" th:value="*{name}"><br>
郵箱:<br>
<input type="text" name="email"th:value="*{email}">
<input type="submit" value="提交">
</form>
<div th:replace="~{fragments/footer :: footer}"></div>
</body>
</html>
list.html:
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org"
xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout">
<head>
<meta charset="UTF-8">
<title>thymeleaf in action</title>
</head>
<body>
<!-- 引用頭部信息 -->
<!-- 在fragments下的header文件下有名為header的片段 -->
<div th:replace="~{fragments/header :: header}"></div>
<h3 th:text="${userModel.title}"></h3>
<div>
<a href="/users/form.html" th:href="@{/users/form}">創(chuàng)建用戶</a>
</div>
<table border="1">
<thead>
<tr>
<td>ID</td>
<td>Email</td>
<td>Name</td>
</tr>
</thead>
<tbody>
<tr th:if="${userModel.userList.size()} eq 0">
<td colspan="3">沒有用戶信息</td>
</tr>
<tr th:each="user : ${userModel.userList}">
<td th:text="${user.id}"></td>
<td th:text="${user.email}"></td>
<td ><a th:href="@{'/users/'+${user.id}}" th:text="${user.name}"></a></td>
</tr>
</tbody>
</table>
<div th:replace="~{fragments/footer :: footer}"></div>
</body>
</html>
view.html:
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org"
xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout">
<head>
<meta charset="UTF-8">
<title>thymeleaf in action</title>
</head>
<body>
<div th:replace="~{fragments/header :: header}"></div>
<h3 th:text="${userModel.title}">test</h3>
<div>
<p><strong>ID:</strong><span th:text="${userModel.user.id}"></span></p>
<p><strong>Name:</strong><span th:text="${userModel.user.name}"></span></p>
<p><strong>Email:</strong><span th:text="${userModel.user.email}"></span></p>
</div>
<div>
<a th:href="@{'/users/delete/'+${userModel.user.id}}">刪除</a>
<a th:href="@{'/users/modify/'+${userModel.user.id}}">修改</a>
</div>
<div th:replace="~{fragments/footer :: footer}"></div>
</body>
</html>
以上頁面就涉及到了thymeleaf的常用標簽,通過這幾個頁面,理解thymeleaf的用法。
7、測試效果:

點擊“創(chuàng)建用戶”:

點擊“提交”后:

點擊name欄可以進入view頁面:

這個頁面還可以進行刪除和修改,這里不再截圖。
總結:
thymeleaf標簽看起來很多,其實常用的也不多,且很好理解。主要別忘了在html標簽中需要加上xmlns:th="http://www.thymeleaf.org" xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout"。如果eclipse寫thymeleaf標簽時沒有提示,安裝一下thymeleaf插件重啟eclipse即可,點擊help --> install new software,地址為:http://www.thymeleaf.org/eclipse-plugin-update-site/.
