Thymeleaf的使用

前言:

最近聽說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的使用。點下載本案例源碼。
項目結構如下:

image.png

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、測試效果:

image.png

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

image.png

點擊“提交”后:

image.png

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

image.png

這個頁面還可以進行刪除和修改,這里不再截圖。

總結:

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/.

image.png

以上內(nèi)容屬于個人筆記整理,如有錯誤,歡迎批評指正!

最后編輯于
?著作權歸作者所有,轉載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容