外化文本把模板代碼從模板文件抽取出來,獨立放到特定的文件中,例如.properties文件,能夠很方便地替換爲不一樣語言的文本表示,外化文本一般叫作消息。css
使用#{…}來引用消息html
模板文件與屬性文件必需要放在同一個目錄下,且文件名也要符合規範:java
/WEB-INF/templates/home.html
jquery
/WEB-INF/templates/home_en.properties
web
/WEB-INF/templates/home_es.properties
算法
/WEB-INF/templates/home_pt_BR.properties
express
/WEB-INF/templates/home.properties
數組
可對消息使用參數:
服務器
home.welcome=¡Bienvenido a nuestra tienda de comestibles, {0}!
消息的參數根據java.text.MessageFormat標準語法來指定:
java.text.MessageFormat標準語法來指定:
<p th:utext="#{home.welcome(${session.user.name})}"> Welcome to our grocery store, Sebastian Pepper! </p>
多個參數使用逗號分隔開
消息的鍵自身也是能夠來自變量:
<p th:utext="#{${welcomeMsgKey}(${session.user.name})}"> Welcome to our grocery store, Sebastian Pepper! </p>
上下文是實現接口
sessionorg.thymeleaf.context.IContext的對象,它把全部模板引擎執行須要的數據包含在一個Map變量中,同時引用用於處理外化文本的Locale。
org.thymeleaf.context.IWebContext繼承了
org.thymeleaf.context.IContext:
public interface IWebContext extends IContext { public HttpSerlvetRequest getHttpServletRequest(); public HttpSession getHttpSession(); public ServletContext getServletContext(); public VariablesMap<String,String[]> getRequestParameters(); public VariablesMap<String,Object> getRequestAttributes(); public VariablesMap<String,Object> getSessionAttributes(); public VariablesMap<String,Object> getApplicationAttributes(); }
它們的實現有兩個:
org.thymeleaf.context.Context
implements IContext
org.thymeleaf.context.WebContext
implements IWebContext
WebContext比Context多作的工做有:
把全部請求屬性添加到上下文map變量中
添加包含全部請求參數的param上下文變量
添加包含全部會話屬性的session上下文變量
添加包含全部ServletContext屬性的application上下文變量
在執行模板解析前,會設置一個叫執行信息(exeInfo)的特殊變量到全部的上下文對象(實現IContext接口,包括Context和WebContext)中,這個變量有兩個可在模板中使用的數據:
${execInfo.templateName} 模板名稱
${execInfo.now} 一個Calendar對象,表示引擎開始執行模板的時間
保留文本原樣
th:text標籤默認會對標籤內的特殊字符作轉義處理
th:utext標籤可讓標籤值中的內容按原樣輸出
使用變量
${…}會基於上下文的map變量執行,從map變量中使用OGNL語言獲取變量值。
${person.father.name}
${person['father']['name']}
${countriesByCode.ES} ${personsByName['Stephen Zucchini'].age}
${personsArray[0].name}
${person.createCompleteName()} ${person.createCompleteNameWithSeparator('-')}
在上下文變量上執行OGNL表達式時,有一些對象在表達式上是可用的,可經過使用#來引用:
#ctx 上下文對象
#vars 上下文變量
#locale 上下文locale
#httpServletRequest (僅Web上下文)HttpServletRequest對象
#httpSession (僅Web上下文)HttpSession對象
例子:
Established locale country: <span th:text="${#locale.country}">US</span>.
變量表達式也能夠寫成*{…},所不一樣的是,星號語法會在一個選定的對象上進行運算,而不是在整個map上下文變量上運算。若是沒有選定的對象,則${…}與*{…}所作的事情都是相同的。
使用th:object來選定對象:
<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> <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>
當選定一個對象時,這個對象能夠在${…}中經過#object表達式變量來引用:
<div th:object="${session.user}"> <p>Name: <span th:text="${#object.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>
若是不選擇對象,則二者是等價的:
<div> <p>Name: <span th:text="*{session.user.name}">Sebastian</span>.</p> <p>Surname: <span th:text="*{session.user.surname}">Pepper</span>.</p> <p>Nationality: <span th:text="*{session.user.nationality}">Saturn</span>.</p> </div>
標準表達式語法
簡單表達式
${…} 變量表達式
*{…} 選擇變量表達式
#{…} 消息表達式
@{…} 連接URL表達式
字面量
文本字面量:‘one text’
<span th:text="'working web application'">template file</span>
數字字面量:0,34,3.0
<span th:text="2013 + 2">1494</span>
布爾字面量:true,false
「== false
」寫在花括號外面,則比較操做由Thymeleaf標準表達式引擎處理== false<div th:if="${user.isAdmin()} == false"> ...「== false
」寫在花括號裏面,則由OGNL/SpEL引擎處理== false<div th:if="${user.isAdmin() == false}"> ...
Null字面量:null
<div th:if="${variable.something} == null"> ...
字面量標誌:one,sometext,main,…
數字、布爾、Null三種字面量其實是字面量token的特例。
這些token能夠在標準表達式中獲得一些簡化,它們的工做原理與文本字面量徹底相同(’…’),但只容許字母(A-Za-z)、數字(0-9)、方括號([])、點(.)、橫線(-)、下劃線(_),所以不能有空白符,不能有逗號等等。
token不須要使用任何引號包圍,所以,可以使用:
<div th:class="content">...</div>替換:<div th:class="'content'">...</div>
文本操做
字符串鏈接:+
th:text="'The name of the user is ' + ${user.name}"
字面量替換:|The name is ${name}|
字面量替換能夠省略「+」操做符:
<span th:text="|Welcome to our application, ${user.name}!|">等價於:<span th:text="'Welcome to our application, ' + ${user.name} + '!'">也能夠結合其它類型的表達式使用:<span th:text="${onevar} + ' ' + |${twovar}, ${threevar}|">注意:只有變量表達式${…}才容許出如今|…|字面量替換中,其它的字面量’…’、布爾/數字token、條件表達式等等都不行
算法操做
二元操做符:+,-,*,/(div),%(mod)
由Thymeleaf標準表達式引擎處理運算
th:with="isEven=(${prodStat.count} % 2 == 0)"由OGNL引擎處理運算th:with="isEven=${prodStat.count % 2 == 0}"
負號(一元操做符):-
布爾操做
二元操做符:and,or
布爾取反(一元操做符):!,not
比較及相等操做
比較操做符:>,<,>=,<=(gt,lt,ge,le)
th:if="${prodStat.count} > 1"
相等操做符:==,!=(eq,ne)
th:text="'Execution mode is ' + ( (${execMode} == 'dev')? 'Development' : 'Production')"
條件操做符
if-then: (if)?(then)
if-then-else:(if)?(the):(else)
<tr th:class="${row.even}? 'even' : 'odd'"> ... </tr>條件表達式中的三個部分自身也是表達式,也能夠是變量(${...}
,*{...}
), 消息(#{...}
), URL (@{...}
) 或字面量 ('...'
)${...}*{...}#{...}@{...}'...'條件表達式也可使用括號來嵌套:<tr th:class="${row.even}? (${row.first}? 'first' : 'even') : 'odd'"> ... </tr>else表達式也能夠省略,當條件爲false時,會返回null:<tr th:class="${row.even}? 'alt'"> ... </tr>
default:(value)?:(defaultValue)
這是沒有then部分的特殊的條件表達式,又叫作Elvis操做,只有在第一個表達式返回null時,第二個表達式纔會運算:
<div th:object="${session.user}"> ... <p>Age: <span th:text="*{age}?: '(no age specified)'">27</span>.</p> </div>等價於:<p>Age: <span th:text="*{age != null}? *{age} : '(no age specified)'">27</span>.</p>也能夠包含嵌套的表達式:<p> Name: <span th:text="*{firstName}?: (*{admin}? 'Admin' : #{default.username})">Sebastian</span> </p>
綜合案例
'User is of type ' + (${user.isAdmin()} ? 'Administrator' : (${user.type} ?: 'Unknown'))
表達式工具對象
#dates 與java.util.Date對象的方法對應,格式化、日期組件抽取等等
#calendars 相似#dates,與java.util.Calendar對象對應
#numbers 格式化數字對象的工具方法
#strings 與java.lang.String對應的工具方法:contains、startsWith、prepending/appending等等
#objects 用於對象的工具方法
#bools 用於布爾運算的工具方法
#arrays 用於數組的工具方法
#lists 用於列表的工具方法
#sets 用於set的工具方法
#maps 用於map的工具方法
#aggregates 用於建立數組或集合的聚合的工具方法
#messages 用於在變量表達式內部獲取外化消息的工具方法,與#{…}語法獲取的方式相同
#ids 用於處理可能重複出現(例如,做爲遍歷的結果)的id屬性的工具方法
連接URL
URL在web模板中是一級重要元素,使用@{…}表示
URL的類型:
絕對URL:http://www.thymeleaf.org
相對URL:
頁面相對: user/login.html
上下文相對:/itemdetails?id=3 (服務器上下文名稱會被自動添加)
服務器相對:~/billing/processInvoice(容許調用同一服務器上的另外一個上下文中的URL)
協議相對://code.jquery.com/jquery-2.0.3.min.js
Thymeleaf在任何狀況下均可以處理絕對URL,對於相對URL,則須要使用一個實現了IWebContext接口的上下文對象,這個對象包含了來自HTTP請求的信息,這些信息用於建立相對連接。
<!-- 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>
Thymeleaf提供預處理表達式的功能。
它是在錶殼式正常執行前執行的操做,容許修改最終將要被執行的表達式。
預處理表達式跟正常的同樣,但被兩個下劃線包圍住,例如:__${expression}__
假設有一個i18n消息文件Message_fr.properties,裏面有一個條目包含了一個調用具體語言的靜態方法的OGNL表達式:
article.text=@myapp.translator.Translator@translateToFrench({0})
Messages_es.properties中的等價條目:
article.text=@myapp.translator.Translator@translateToSpanish({0})
能夠根據locale先建立用於運算表達式的標記片斷,本例中,先經過預處理選擇表達式,而後讓Thymeleaf處理這個選擇出來的表達式:
<p th:text="${__#{article.text('textVar')}__}">Some text here...</p>
對於locale爲French的狀況,上面的表達式通過預處理後,得出的等價物以下:
<p th:text="${@myapp.translator.Translator@translateToFrench(textVar)}">Some text here...</p>
設置屬性值
th:attr任何屬性值
<form action="subscribe.html" th:attr="action=@{/subscribe}"> <fieldset> <input type="text" name="email" /> <input type="submit" value="Subscribe me!" th:attr="value=#{subscribe.submit}"/> </fieldset> </form>多個屬性一塊兒設置<img src="../../images/gtvglogo.png" th:attr="src=@{/images/gtvglogo.png},title=#{logo},alt=#{logo}" />
設置指定屬性
<input type="submit" value="Subscribe me!" th:value="#{subscribe.submit}"/><form action="subscribe.html" th:action="@{/subscribe}"><li><a href="product/list.html" th:href="@{/product/list}">Product List</a></li>全部的指定屬性:| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |th:abbrth:acceptth:accept-charsetth:accesskeyth:actionth:alignth:altth:archiveth:audioth:autocompleteth:axisth:backgroundth:bgcolorth:borderth:cellpaddingth:cellspacingth:challengeth:charsetth:citeth:classth:classidth:codebaseth:codetypeth:colsth:colspanth:compactth:contentth:contenteditableth:contextmenuth:datath:datetimeth:dirth:draggableth:dropzoneth:enctypeth:forth:formth:formactionth:formenctypeth:formmethodth:formtargetth:frameth:frameborderth:headersth:heightth:highth:hrefth:hreflangth:hspaceth:http-equivth:iconth:idth:keytypeth:kindth:labelth:langth:listth:longdescth:lowth:manifestth:marginheightth:marginwidthth:maxth:maxlengthth:mediath:methodth:minth:nameth:optimumth:patternth:placeholderth:posterth:preloadth:radiogroupth:relth:revth:rowsth:rowspanth:rulesth:sandboxth:schemeth:scopeth:scrollingth:sizeth:sizesth:spanth:spellcheckth:srcth:srclangth:standbyth:startth:stepth:styleth:summaryth:tabindexth:targetth:titleth:typeth:usemapth:valueth:valuetypeth:vspaceth:widthth:wrapth:xmlbaseth:xmllangth:xmlspace
<input type="button" value="Do it!" class="btn" th:attrappend="class=${' ' + cssStyle}" /><tr th:each="prod : ${prods}" class="row" th:classappend="${prodStat.odd}? 'odd'">
修復的布爾屬性
<input type="checkbox" name="active" th:checked="${user.active}" />全部修復的布爾屬性:-| | | | | | | | | | | | | || | | | | | | | | | | | | | | | | | |th:asyncth:autofocusth:autoplayth:checkedth:controlsth:declareth:defaultth:deferth:disabledth:formnovalidateth:hiddenth:ismapth:loopth:multipleth:novalidateth:nowrapth:openth:pubdateth:readonlyth:requiredth:reversedth:scopedth:seamlessth:selected
<table> <tr data-th-each="user : ${users}"> <td data-th-text="${user.login}">...</td> <td data-th-text="${user.name}">...</td> </tr> </table>
data-{prefix}-{name}是編寫HTML5自定義屬性的標準語法,不須要開發者使用th:*這樣的命名空間,Thymeleaf讓這種語法自動對全部dialect均可用。
遍歷
基礎
<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>可遍歷的對象:實現java.util.Iterable、
java.util.Iterable、java.util.Map(遍歷時取
java.util.Map.Entry
)、array、任何對象都被看成只有對象自身一個元素的列表java.util.Map(遍歷時取
java.util.Map(遍歷時取java.util.Map.Entry
)、array、任何對象都被看成只有對象自身一個元素的列表java.util.Map.Entry
)、array、任何對象都被看成只有對象自身一個元素的列表java.util.Map.Entry
狀態
當前遍歷索引,從0開始,index屬性
當前遍歷索引,從1開始,count屬性
總元素數量,size屬性
每一次遍歷的iter變量,current屬性
當前遍歷是even仍是odd,even/odd布爾屬性
當前遍歷是第一個,first布爾屬性
當前遍歷是最後一個,last布爾屬性
<tr th:each="prod,iterStat : ${prods}" th:class="${iterStat.odd}? 'odd'"> <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>
若不指定狀態變量,Thymeleaf會默認生成一個名爲「變量名Stat」的狀態變量:
<tr th:each="prod : ${prods}" th:class="${prodStat.odd}? 'odd'"> <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>
條件運算
<tr th:each="prod : ${prods}" th:class="${prodStat.odd}? 'odd'"> <td th:text="${prod.name}">Onions</td> <td th:text="${prod.price}">2.41</td> <td th:text="${prod.inStock}? #{true} : #{false}">yes</td> <td> <span th:text="${#lists.size(prod.comments)}">2</span> comment/s <a href="comments.html" th:href="@{/product/comments(prodId=${prod.id})}" th:if="${not #lists.isEmpty(prod.comments)}">view</a> </td> </tr>
<a href="comments.html" th:href="@{/product/comments(prodId=${prod.id})}" th:if="${not #lists.isEmpty(prod.comments)}">view</a>
th:if不僅運算布爾條件,它對如下狀況也運算爲true:
值不爲null
值爲boolean且爲true
值爲數字且非0
值爲字符且非0
值是字符串且不是:「false」,「off」,「no」
值不是boolean、數字、字符、字符串
若是值爲null,則th:if運算結果爲false
<a href="comments.html" th:href="@{/comments(prodId=${prod.id})}" th:unless="${#lists.isEmpty(prod.comments)}">view</a>
th:if的反面是th:unless
<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>
<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>