Spring Boot 2.0 整合 Thymeleaf 模塊引擎

本文首發(fā)于:https://y0ngb1n.github.io/a/567589f9.html

開發(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:自動裝配 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ā)時關(guān)閉緩存,不然沒法看到實時頁面尖阔!
    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 中可見 Thymeleaf3.0.0 版本開始使用 HTML 替代 HTML5、LEGACYHTML5张症、XHTML仓技、VALIDXHTML。如果還在使用 3.0.0 以前的版本俗他,想要使用非嚴(yán)格的 HTML脖捻,需要做以下配置:

  • pom.xml 中引入 nekohtml 依賴
  • application.yml 中配置 spring.thymeleaf.mode=LEGACYHTML5

更多屬性配置請參考「Appendix A. Common application properties」中 # THYMELEAF (ThymeleafAutoConfiguration) 模塊的屬性介紹。(TIPS:使用 CTRL + F 進行快速定位)

創(chuàng)建測試 Controller

創(chuàng)建一個 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)建測試 HTML 頁面

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 識別 Thymeleaf 命名空間摩疑,這樣在標(biāo)簽里輸入 th: 后危融,IDE 會提示相應(yīng)的語法替久,方便開發(fā)分冈!不加入這句代碼也不會影響 Thymeleaf 模板引擎的渲染规肴,以及頁面的正常顯示嗅绰。

測試訪問

啟動成功后,訪問 http://127.0.0.1:8080炼蹦,即可看到效果:

Hello Thymeleaf

訪問結(jié)果:Hello Thymeleaf!


Thymeleaf 常用語法

獲取變量值

<p th:text="'Hello! ' + ${name} + '!'" >name</p>

可以看出獲取變量值用 $ 符號凹髓,對于 JavaBean 的話使用 變量名.屬性名 方式獲取村斟,這點和 EL 表達式一樣鸠删。

另外 $ 表達式只能寫在 th 標(biāo)簽內(nèi)部抱完,不然不會生效,上面例子就是使用 th:text 標(biāo)簽的值替換 <p>...</p> 標(biāo)簽里面的值刃泡,至于 p 里面的原有的值只是為了給前端開發(fā)時做展示用的巧娱。這樣的話很好的做到了前后端分離。

內(nèi)容信息輸出:th:textth:utext

  • th:text:以純文本的方式輸出
  • th:utext:以 HTML 標(biāo)簽的方式輸出烘贴,瀏覽器能正常渲染
`th:text` 與 `th:utext`

HTML 代碼:

<body>
  <h2 th:text="' th:text &nbsp ? ' + ${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

對于 URL 的處理是通過語法 @{…} 來處理的:

引用 URL

HTML 代碼:

<body>
  <ul>
    <li>
      <a th:href="@{https://github.com/{username}(username=${username})}">絕對路徑 1</a>,
      <a th:href="@{https://www.baidu.com}">絕對路徑 2</a>
    </li>
    <li>
      <a th:href="@{/}">相對路徑</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:hrefth:src

字符串替換

很多時候可能我們只需要對一大段文字中的某一處地方進行替換上荡,可以通過字符串拼接操作完成:

<p th:text="'Welcome to our application, ' + ${user.name} + '!'">

可以用另一種更簡潔的方式:

<p th:text="|Welcome to our application, ${user.name}!|">

文字替換本身可以和與其他表達式聯(lián)合使用:

<p th:text="${onevar} + ', ' + |${twovar}, ${threevar}|">

當(dāng)然這種形式限制比較多趴樱,|…| 中只能包含變量表達式 ${…}馒闷,不能包含其他常量、條件表達式等叁征。

字符串替換

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";
}

運算符

在表達式中可以使用各類算術(shù)運算符纳账,例如 +, -, *, /, %

th:with="isEven=(${user.age} % 2 == 0)"

邏輯運算符 >, <, <=, >=, ==, != 都可以使用,唯一需要注意的是使用 <, > 時需要用它的 HTML 轉(zhuǎn)義符:

th:if="${user.age} &gt; 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}  &gt; 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:ifth:unless 屬性進行條件判斷,下面的例子中啤呼,標(biāo)簽只有在 th:if 中條件成立時才顯示:

<a th:href="@{/login}" th:if=${user == null}>Login</a>
<a th:href="@{/login}" th:unless=${user != null}>Login</a>

th:unlessth:if 恰好相反卧秘,只有表達式中的條件不成立,才會顯示其內(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>

消息表達式:#{...}翅敌,也稱為文本外部化、國際化或 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ù)是一種非常常見的場景蚯涮,例如現(xiàn)在有 n 條記錄需要渲染成一個表格治专,該數(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}" 意味著對集合變量 prods 進行遍歷,循環(huán)變量是 prod 在循環(huán)體中可以通過表達式訪問棒旗。

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";
}
循環(huán)

更多標(biāo)簽用法請參考「Thymeleaf 常用語法」喘批、「Thymeleaf 參考手冊」解鎖更多技巧 ??


參考資料

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市铣揉,隨后出現(xiàn)的幾起案子谤祖,更是在濱河造成了極大的恐慌,老刑警劉巖老速,帶你破解...
    沈念sama閱讀 219,589評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件粥喜,死亡現(xiàn)場離奇詭異,居然都是意外死亡橘券,警方通過查閱死者的電腦和手機额湘,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,615評論 3 396
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來旁舰,“玉大人锋华,你說我怎么就攤上這事〖埽” “怎么了毯焕?”我有些...
    開封第一講書人閱讀 165,933評論 0 356
  • 文/不壞的土叔 我叫張陵,是天一觀的道長磺樱。 經(jīng)常有香客問我纳猫,道長,這世上最難降的妖魔是什么竹捉? 我笑而不...
    開封第一講書人閱讀 58,976評論 1 295
  • 正文 為了忘掉前任芜辕,我火速辦了婚禮,結(jié)果婚禮上块差,老公的妹妹穿的比我還像新娘侵续。我一直安慰自己,他們只是感情好憨闰,可當(dāng)我...
    茶點故事閱讀 67,999評論 6 393
  • 文/花漫 我一把揭開白布状蜗。 她就那樣靜靜地躺著,像睡著了一般鹉动。 火紅的嫁衣襯著肌膚如雪轧坎。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,775評論 1 307
  • 那天训裆,我揣著相機與錄音眶根,去河邊找鬼蜀铲。 笑死,一個胖子當(dāng)著我的面吹牛属百,可吹牛的內(nèi)容都是我干的记劝。 我是一名探鬼主播,決...
    沈念sama閱讀 40,474評論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼族扰,長吁一口氣:“原來是場噩夢啊……” “哼厌丑!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起渔呵,我...
    開封第一講書人閱讀 39,359評論 0 276
  • 序言:老撾萬榮一對情侶失蹤怒竿,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后扩氢,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體耕驰,經(jīng)...
    沈念sama閱讀 45,854評論 1 317
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,007評論 3 338
  • 正文 我和宋清朗相戀三年录豺,在試婚紗的時候發(fā)現(xiàn)自己被綠了朦肘。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 40,146評論 1 351
  • 序言:一個原本活蹦亂跳的男人離奇死亡双饥,死狀恐怖媒抠,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情咏花,我是刑警寧澤趴生,帶...
    沈念sama閱讀 35,826評論 5 346
  • 正文 年R本政府宣布,位于F島的核電站昏翰,受9級特大地震影響苍匆,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜矩父,卻給世界環(huán)境...
    茶點故事閱讀 41,484評論 3 331
  • 文/蒙蒙 一锉桑、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧窍株,春花似錦、人聲如沸攻柠。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,029評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽瑰钮。三九已至冒滩,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間浪谴,已是汗流浹背开睡。 一陣腳步聲響...
    開封第一講書人閱讀 33,153評論 1 272
  • 我被黑心中介騙來泰國打工因苹, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人篇恒。 一個月前我還...
    沈念sama閱讀 48,420評論 3 373
  • 正文 我出身青樓扶檐,卻偏偏與公主長得像,于是被迫代替她去往敵國和親胁艰。 傳聞我的和親對象是個殘疾皇子款筑,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 45,107評論 2 356

推薦閱讀更多精彩內(nèi)容