工具集核心教程 | 第三篇: Thymeleaf模板引擎入門到進階

thymeleaf介紹

簡單說, Thymeleaf 是一個跟 Velocity、FreeMarker 相似的模板引擎,它能夠徹底替代 JSP。相較與其餘的模板引擎,它有以下三個極吸引人的特色:javascript

1.Thymeleaf 在有網絡和無網絡的環境下皆可運行,即它可讓美工在瀏覽器查看頁面的靜態效果,也可讓程序員在服務器查看帶數據的動態頁面效果。這是因爲它支持 html 原型,而後在 html 標籤裏增長額外的屬性來達到模板+數據的展現方式。瀏覽器解釋 html 時會忽略未定義的標籤屬性,因此 thymeleaf 的模板能夠靜態地運行;當有數據返回到頁面時,Thymeleaf 標籤會動態地替換掉靜態內容,使頁面動態顯示。

2.Thymeleaf 開箱即用的特性。它提供標準和spring標準兩種方言,能夠直接套用模板實現JSTL、 OGNL表達式效果,避免天天套模板、該jstl、改標籤的困擾。同時開發人員也能夠擴展和建立自定義的方言。

3.Thymeleaf 提供spring標準方言和一個與 SpringMVC 完美集成的可選模塊,能夠快速的實現表單綁定、屬性編輯器、國際化等功能。

標準表達式語法

它們分爲四類:php

1.變量表達式
2.選擇或星號表達式
3.文字國際化表達式
4.URL表達式

變量表達式

變量表達式即OGNL表達式或Spring EL表達式(在Spring術語中也叫model attributes)。以下所示:
${session.user.name}html

它們將以HTML標籤的一個屬性來表示:前端

<span th:text="${book.author.name}">  
<li th:each="book : ${books}">

選擇(星號)表達式

選擇表達式很像變量表達式,不過它們用一個預先選擇的對象來代替上下文變量容器(map)來執行,以下:
*{customer.name}java

被指定的objectth:object屬性定義:python

<div th:object="${book}">  
     ...  
    <span th:text="*{title}">...</span>  
    ...  
 </div>

文字國際化表達式

文字國際化表達式容許咱們從一個外部文件獲取區域文字信息(.properties),用Key索引Value,還能夠提供一組參數(可選).程序員

#{main.title}  
  #{message.entrycreated(${entryId})}

能夠在模板文件中找到這樣的表達式代碼:web

<table>  
    ...  
   <th th:text="#{header.address.city}">...</th>  
   <th th:text="#{header.address.country}">...</th>  
   ...  
 </table>

URL表達式

URL表達式指的是把一個有用的上下文或回話信息添加到URL,這個過程常常被叫作URL重寫。面試

@{/order/list}

URL還能夠設置參數:spring

@{/order/details(id=${orderId})}

相對路徑:

@{../documents/report}

讓咱們看這些表達式:

<form th:action="@{/createOrder}">  
   <a href="main.html" th:href="@{/main}">

變量表達式和星號表達有什麼區別嗎?

若是不考慮上下文的狀況下,二者沒有區別;星號語法評估在選定對象上表達,而不是整個上下文
什麼是選定對象?就是父標籤的值,以下:

<div th:object="${session.user}">
    <p>Name: <span th:text="*{firstName}">Sebastian</span>.</p>
    <p>Surname: <span th:text="*{lastName}">Pepper</span>.</p>
    <p>Nationality: <span th:text="*{nationality}">Saturn</span>.</p>
  </div>

這是徹底等價於:

<div th:object="${session.user}">
      <p>Name: <span th:text="${session.user.firstName}">Sebastian</span>.</p>
      <p>Surname: <span th:text="${session.user.lastName}">Pepper</span>.</p>
      <p>Nationality: <span th:text="${session.user.nationality}">Saturn</span>.</p>
  </div>

固然,美圓符號和星號語法能夠混合使用:

<div th:object="${session.user}">
      <p>Name: <span th:text="*{firstName}">Sebastian</span>.</p>
      <p>Surname: <span th:text="${session.user.lastName}">Pepper</span>.</p>
      <p>Nationality: <span th:text="*{nationality}">Saturn</span>.</p>
  </div>

表達式支持的語法

字面(Literals)

文本文字(Text literals): 'one text', 'Another one!',…
數字文本(Number literals): 0, 34, 3.0, 12.3,…
布爾文本(Boolean literals): true, false
空(Null literal): null
文字標記(Literal tokens): one, sometext, main,…

文本操做(Text operations)

字符串鏈接(String concatenation): +
文本替換(Literal substitutions): |The name is ${name}|

算術運算(Arithmetic operations)

二元運算符(Binary operators): +, -, *, /, %
減號(單目運算符)Minus sign (unary operator): -

布爾操做(Boolean operations)

二元運算符(Binary operators):and, or
布爾否認(一元運算符)Boolean negation (unary operator):!, not

比較和等價(Comparisons and equality)

比較(Comparators): >, <, >=, <= (gt, lt, ge, le)
等值運算符(Equality operators):==, != (eq, ne)

條件運算符(Conditional operators)

If-then: (if) ? (then)
If-then-else: (if) ? (then) : (else)
Default: (value) ?: (defaultvalue)

全部這些特徵能夠被組合並嵌套:

'User is of type ' + (${user.isAdmin()} ? 'Administrator' : (${user.type} ?: 'Unknown'))

經常使用th標籤都有那些?

關鍵字 功能介紹 案例
th:id 替換id <input th:id="'xxx' + ${collect.id}"/>
th:text 文本替換 <p th:text="${collect.description}">description</p>
th:utext 支持html的文本替換 <p th:utext="${htmlcontent}">conten</p>
th:object 替換對象 <div th:object="${session.user}">
th:value 屬性賦值 <input th:value="${user.name}" />
th:with 變量賦值運算 <div th:with="isEven=${prodStat.count}%2==0"></div>
th:style 設置樣式 th:style="'display:' + @{(${sitrue} ? 'none' : 'inline-block')} + ''"
th:onclick 點擊事件 th:onclick="'getCollect()'"
th:each 屬性賦值 tr th:each="user,userStat:${users}">
th:if 判斷條件 <a th:if="${userId == collect.userId}" >
th:unless th:if判斷相反 <a th:href="@{/login}" th:unless=${session.user != null}>Login</a>
th:href 連接地址 <a th:href="@{/login}" th:unless=${session.user != null}>Login</a> />
th:switch 多路選擇 配合th:case 使用 <div th:switch="${user.role}">
th:case th:switch的一個分支 <p th:case="'admin'">User is an administrator</p>
th:fragment 佈局標籤,定義一個代碼片斷,方便其它地方引用 <div th:fragment="alert">
th:include 佈局標籤,替換內容到引入的文件 <head th:include="layout :: htmlhead" th:with="title='xx'"></head> />
th:replace 佈局標籤,替換整個標籤到引入的文件 <div th:replace="fragments/header :: title"></div>
th:selected selected選擇框 選中 th:selected="(${xxx.id} == ${configObj.dd})"
th:src 圖片類地址引入 <img class="img-responsive" alt="App Logo" th:src="@{/img/logo.png}" />
th:inline 定義js腳本可使用變量 <script type="text/javascript" th:inline="javascript">
th:action 表單提交的地址 <form action="subscribe.html" th:action="@{/subscribe}">
th:remove 刪除某個屬性 <tr th:remove="all"> 1.all:刪除包含標籤和全部的孩子。2.body:不包含標記刪除,但刪除其全部的孩子。3.tag:包含標記的刪除,但不刪除它的孩子。4.all-but-first:刪除全部包含標籤的孩子,除了第一個。5.none:什麼也不作。這個值是有用的動態評估。
th:attr 設置標籤屬性,多個屬性能夠用逗號分隔 好比 th:attr="src=@{/image/aa.jpg},title=#{logo}",此標籤不太優雅,通常用的比較少。

還有很是多的標籤,這裏只列出最經常使用的幾個,因爲一個標籤內能夠包含多個th:x屬性,其生效的優先級順序爲:

include,each,if/unless/switch/case,with,attr/attrprepend/attrappend,value/href,src ,etc,text/utext,fragment,remove。

幾種經常使用的使用方法

一、賦值、字符串拼接

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

字符串拼接還有另一種簡潔的寫法

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

二、條件判斷 If/Unless

Thymeleaf中使用th:ifth:unless屬性進行條件判斷,下面的例子中,<a>標籤只有在th:if中條件成立時才顯示:

<a th:if="${myself=='yes'}" > </i> </a>
<a th:unless=${session.user != null} th:href="@{/login}" >Login</a>

th:unlessth:if剛好相反,只有表達式中的條件不成立,纔會顯示其內容。

也可使用 (if) ? (then) : (else) 這種語法來判斷顯示的內容

三、for 循環

<tr  th:each="collect,iterStat : ${collects}"> 
     <th scope="row" th:text="${collect.id}">1</th>
     <td >
        <img th:src="${collect.webLogo}"/>
     </td>
     <td th:text="${collect.url}">Mark</td>
     <td th:text="${collect.title}">Otto</td>
     <td th:text="${collect.description}">@mdo</td>
     <td th:text="${terStat.index}">index</td>
 </tr>

iterStat稱做狀態變量,屬性有:

index:當前迭代對象的index(從0開始計算)
count: 當前迭代對象的index(從1開始計算)
size:被迭代對象的大小
current:當前迭代變量
even/odd:布爾值,當前循環是不是偶數/奇數(從0開始計算)
first:布爾值,當前循環是不是第一個
last:布爾值,當前循環是不是最後一個

四、URL

URLWeb應用模板中佔據着十分重要的地位,須要特別注意的是Thymeleaf對於URL的處理是經過語法@{...}來處理的。
若是須要ThymeleafURL進行渲染,那麼務必使用th:href,th:src等屬性,下面是一個例子

<!-- Will produce 'http://localhost:8080/standard/unread' (plus rewriting) -->
 <a  th:href="@{/standard/{type}(type=${type})}">view</a>

<!-- Will produce '/gtvg/order/3/details' (plus rewriting) -->
<a href="details.html" th:href="@{/order/{orderId}/details(orderId=${o.id})}">view</a>

設置背景

<div th:style="'background:url(' + @{/<path-to-image>} + ');'"></div>

根據屬性值改變背景

<div class="media-object resource-card-image"  th:style="'background:url(' + @{(${collect.webLogo}=='' ? 'img/favicon.png' : ${collect.webLogo})} + ')'" ></div>

幾點說明:

上例中`URL`最後的`(orderId=${o.id})` 表示將括號內的內容做爲`URL`參數處理,該語法避免使用字符串拼接,大大提升了可讀性
`@{...}`表達式中能夠經過`{orderId}`訪問`Context`中的`orderId`變量
`@{/order}`是`Context`相關的相對路徑,在渲染時會自動添加上當前`Web`應用的`Context`名字,假設`Context`名字爲`app`,那麼結果應該是`/app/order`

五、內聯js

內聯文本:[[...]]內聯文本的表示方式,使用時,必須先用th:inline="text/javascript/none"激活,th:inline能夠在父級標籤內使用,甚至做爲body的標籤。內聯文本儘管比th:text的代碼少,不利於原型顯示。

<script th:inline="javascript">
/*<![CDATA[*/
...
var username = /*[[${sesion.user.name}]]*/ 'Sebastian';
var size = /*[[${size}]]*/ 0;
...
/*]]>*/
</script>

js附加代碼:

/*[+
var msg = 'This is a working application';
+]*/

js移除代碼:

/*[- */
var msg = 'This is a non-working template';
/* -]*/

六、內嵌變量

爲了模板更加易用,Thymeleaf還提供了一系列Utility對象(內置於Context中),能夠經過#直接訪問:

`dates` : `java.util.Date`的功能方法類。
 `calendars` : 相似`#dates`,面向`java.util.Calendar`
 `numbers` : 格式化數字的功能方法類
 `strings` : 字符串對象的功能類,`contains,startWiths,prepending/appending`等等。
 `objects`: 對`objects`的功能類操做。
 `bools`: 對布爾值求值的功能方法。
 `arrays`:對數組的功能類方法。
 `lists`: 對`lists`功能類方法
 `sets`
 `maps`
 `...`

下面用一段代碼來舉例一些經常使用的方法:

dates

/*
 * Format date with the specified pattern
 * Also works with arrays, lists or sets
 */
${#dates.format(date, 'dd/MMM/yyyy HH:mm')}
${#dates.arrayFormat(datesArray, 'dd/MMM/yyyy HH:mm')}
${#dates.listFormat(datesList, 'dd/MMM/yyyy HH:mm')}
${#dates.setFormat(datesSet, 'dd/MMM/yyyy HH:mm')}

/*
 * Create a date (java.util.Date) object for the current date and time
 */
${#dates.createNow()}

/*
 * Create a date (java.util.Date) object for the current date (time set to 00:00)
 */
${#dates.createToday()}

strings

/*
 * Check whether a String is empty (or null). Performs a trim() operation before check
 * Also works with arrays, lists or sets
 */
${#strings.isEmpty(name)}
${#strings.arrayIsEmpty(nameArr)}
${#strings.listIsEmpty(nameList)}
${#strings.setIsEmpty(nameSet)}

/*
 * Check whether a String starts or ends with a fragment
 * Also works with arrays, lists or sets
 */
${#strings.startsWith(name,'Don')}                  // also array*, list* and set*
${#strings.endsWith(name,endingFragment)}           // also array*, list* and set*

/*
 * Compute length
 * Also works with arrays, lists or sets
 */
${#strings.length(str)}

/*
 * Null-safe comparison and concatenation
 */
${#strings.equals(str)}
${#strings.equalsIgnoreCase(str)}
${#strings.concat(str)}
${#strings.concatReplaceNulls(str)}

/*
 * Random
 */
${#strings.randomAlphanumeric(count)}

使用thymeleaf佈局

使用thymeleaf佈局很是的方便

定義代碼片斷:

<footer th:fragment="copy"> 
&copy; 2016
</footer>

在頁面任何地方引入:

<body> 
  <div th:include="footer :: copy"></div>
  <div th:replace="footer :: copy"></div>
 </body>

th:includeth:replace區別,include只是加載,replace是替換

返回的HTML以下:

<body> 
   <div> &copy; 2016 </div> 
  <footer>&copy; 2016 </footer> 
</body>

下面是一個經常使用的後臺頁面佈局,將整個頁面分爲頭部,尾部、菜單欄、隱藏欄,點擊菜單隻改變content區域的頁面

<body class="layout-fixed">
  <div th:fragment="navbar"  class="wrapper"  role="navigation">
    <div th:replace="fragments/header :: header">Header</div>
    <div th:replace="fragments/left :: left">left</div>
    <div th:replace="fragments/sidebar :: sidebar">sidebar</div>
    <div layout:fragment="content" id="content" ></div>
    <div th:replace="fragments/footer :: footer">footer</div>
  </div>
</body>

任何頁面想使用這樣的佈局值只須要替換中見的 content模塊便可

<html xmlns:th="http://www.thymeleaf.org" layout:decorator="layout">
   <body>
      <section layout:fragment="content">
    ...

也能夠在引用模版的時候傳參

<head th:include="layout :: htmlhead" th:with="title='Hello'"></head>

layout 是文件地址,若是有文件夾能夠這樣寫 fileName/layout:htmlhead
htmlhead 是指定義的代碼片斷 如th:fragment="copy"

參考

新一代Java模板引擎Thymeleaf
Thymeleaf基本知識
thymeleaf總結文章
Thymeleaf 模板的使用
thymeleaf 學習筆記

寫在最後

歡迎關注喜歡、和點贊後續將推出更多的工具集教程,敬請期待。
歡迎關注個人微信公衆號獲取更多更全的學習資源,視頻資料,技術乾貨!
歡迎掃碼關注

公衆號回覆「學習」,拉你進程序員技術討論羣乾貨資源第一時間分享。

公衆號回覆「視頻」,領取800GJava視頻學習資源。
java學習全套
820G資源

公衆號回覆「全棧」,領取1T前端Java產品經理微信小程序Python等資源合集大放送。
全棧資料
java
python
機器學習
產品經理
接近1T資源

公衆號回覆「慕課」,領取1T慕課實戰學習資源。
慕課實戰大全
php
python
測試
後端
前端
前端
微信
1061G資源

公衆號回覆「實戰」,領取750G項目實戰學習資源。
先後端實戰項目
750實戰資源

公衆號回覆「面試」,領取8G面試實戰學習資源。
JAVA面試實戰視頻

傳智面試講解
8G面試資源

相關文章
相關標籤/搜索