Thymeleaf初探
相比於其餘的模板引擎,Thymeleaf最大的特色是經過HTML的標籤屬性渲染標籤內容,如下是一個Thymeleaf模板例子:css
<!DOCTYPE html SYSTEM "http://www.thymeleaf.org/dtd/xhtml1-strict-thymeleaf-4.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" xmlns:th="http://www.thymeleaf.org"> <head> <title>Good Thymes Virtual Grocery</title> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> <link rel="stylesheet" type="text/css" media="all" href="../../css/gtvg.css" th:href="@{/css/gtvg.css}" /> </head> <body> <p th:text="#{home.welcome}">Welcome to our grocery store!</p> </body> </html>
這是一段標準的HTML代碼,這也就意味着經過瀏覽器直接打開它是能夠正確解析它的結構並看到頁面的樣子。相比去其餘的模板引擎在指定的位置經過${}
等表達式進行渲染,Thymeleaf則是一種針對HTML/XML定製的模板語言(固然它能夠被擴展),它經過標籤中的th:text
屬性來填充該標籤的一段內容。上例中,<p th:text="#{home.welcome}">Welcome to our grocery store!</p>
意味着<p>
標籤中的內容會被表達式#{home.welcome}
的值所替代,不管模板中它的內容是什麼,之因此在模板中「畫蛇添足「地填充它的內容,徹底是爲了它可以做爲原型在瀏覽器中直接顯示出來。html
標準表達式語法
變量
Thymeleaf模板引擎在進行模板渲染時,還會附帶一個Context存放進行模板渲染的變量,在模板中定義的表達式本質上就是從Context中獲取對應的變量的值:前端
<p>Today is: <span th:text="${today}">13 february 2011</span>.</p>
假設today
的值爲2015年8月14日
,那麼渲染結果爲:<p>Today is: 2015年8月14日.</p>
。可見Thymeleaf的基本變量和JSP同樣,都使用${.}
表示獲取變量的值。java
URL
URL在Web應用模板中佔據着十分重要的地位,須要特別注意的是Thymeleaf對於URL的處理是經過語法@{...}
來處理的。Thymeleaf支持絕對路徑URL:後端
<a th:href="@{http://www.thymeleaf.org}">Thymeleaf</a>
同時也可以支持相對路徑URL:瀏覽器
- 當前頁面相對路徑URL——
user/login.html
,一般不推薦這樣寫。 - Context相關URL——
/static/css/style.css
另外,若是須要Thymeleaf對URL進行渲染,那麼務必使用th:href
,th:src
等屬性,下面是一個例子服務器
<!-- Will produce 'http://localhost:8080/gtvg/order/details?orderId=3' (plus rewriting) --> <a href="details.html" th:href="@{http://localhost:8080/gtvg/order/details(orderId=${o.id})}">view</a> <!-- Will produce '/gtvg/order/details?orderId=3' (plus rewriting) --> <a href="details.html" th:href="@{/order/details(orderId=${o.id})}">view</a> <!-- Will produce '/gtvg/order/3/details' (plus rewriting) --> <a href="details.html" th:href="@{/order/{orderId}/details(orderId=${o.id})}">view</a>
幾點說明:session
- 上例中URL最後的(orderId=${o.id})表示將括號內的內容做爲URL參數處理,該語法避免使用字符串拼接,大大提升了可讀性
@{...}
表達式中能夠經過{orderId}
訪問Context中的orderId
變量@{/order}
是Context相關的相對路徑,在渲染時會自動添加上當前Web應用的Context名字,假設context名字爲app,那麼結果應該是/app/order
字符串替換
不少時候可能咱們只須要對一大段文字中的某一處地方進行替換,能夠經過字符串拼接操做完成:前端工程師
<span th:text="'Welcome to our application, ' + ${user.name} + '!'">
一種更簡潔的方式是:app
<span th:text="|Welcome to our application, ${user.name}!|">
固然這種形式限制比較多,|...|
中只能包含變量表達式${...}
,不能包含其餘常量、條件表達式等。
運算符
在表達式中可使用各種算術運算符,例如+, -, *, /, %
th:with="isEven=(${prodStat.count} % 2 == 0)"
邏輯運算符>
, <
, <=
,>=
,==
,!=
均可以使用,惟一須要注意的是使用<
,>
時須要用它的HTML轉義符:
th:if="${prodStat.count} > 1" th:text="'Execution mode is ' + ( (${execMode} == 'dev')? 'Development' : 'Production')"
循環
渲染列表數據是一種很是常見的場景,例如如今有n條記錄須要渲染成一個表格<table>
,該數據集合必須是能夠遍歷的,使用th:each
標籤:
<body> <h1>Product list</h1> <table> <tr> <th>NAME</th> <th>PRICE</th> <th>IN STOCK</th> </tr> <tr th:each="prod : ${prods}"> <td th:text="${prod.name}">Onions</td> <td th:text="${prod.price}">2.41</td> <td th:text="${prod.inStock}? #{true} : #{false}">yes</td> </tr> </table> <p> <a href="../home.html" th:href="@{/}">Return to home</a> </p> </body>
能夠看到,須要在被循環渲染的元素(這裏是<tr>
)中加入th:each
標籤,其中th:each="prod : ${prods}"
意味着對集合變量prods
進行遍歷,循環變量是prod
在循環體中能夠經過表達式訪問。
條件求值
If/Unless
Thymeleaf中使用th:if
和th:unless
屬性進行條件判斷,下面的例子中,<a>
標籤只有在th:if
中條件成立時才顯示:
<a th:href="@{/login}" th:unless=${session.user != null}>Login</a>
th:unless
於th:if
剛好相反,只有表達式中的條件不成立,纔會顯示其內容。
Switch
Thymeleaf一樣支持多路選擇Switch結構:
<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>
默認屬性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>
Utilities
爲了模板更加易用,Thymeleaf還提供了一系列Utility對象(內置於Context中),能夠經過#
直接訪問:
#dates
#calendars
#numbers
#strings
arrays
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)}
頁面即原型
在Web開發過程當中一個繞不開的話題就是前端工程師與後端工程師的協做,在傳統Java Web開發過程當中,前端工程師和後端工程師同樣,也須要安裝一套完整的開發環境,而後各種Java IDE中修改模板、靜態資源文件,啓動/重啓/從新加載應用服務器,刷新頁面查看最終效果。
但實際上前端工程師的職責更多應該關注於頁面自己而非後端,使用JSP,Velocity等傳統的Java模板引擎很難作到這一點,由於它們必須在應用服務器中渲染完成後才能在瀏覽器中看到結果,而Thymeleaf從根本上顛覆了這一過程,經過屬性進行模板渲染不會引入任何新的瀏覽器不能識別的標籤,例如JSP中的<form:input>
,不會在Tag內部寫表達式。整個頁面直接做爲HTML文件用瀏覽器打開,幾乎就能夠看到最終的效果,這大大解放了前端工程師的生產力,它們的最終交付物就是純的HTML/CSS/JavaScript文件。