Thymeleaf

th:text及外化文本

外化文本把模板代碼從模板文件抽取出來,獨立放到特定的文件中,例如.properties文件,能夠很方便地替換爲不一樣語言的文本表示,外化文本一般叫作消息。css

使用#{…}來引用消息html

 

模板文件與屬性文件必需要放在同一個目錄下,且文件名也要符合規範:java

/WEB-INF/templates/home.htmljquery

/WEB-INF/templates/home_en.propertiesweb

/WEB-INF/templates/home_es.properties算法

/WEB-INF/templates/home_pt_BR.propertiesexpress

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

 

上下文

上下文是實現接口org.thymeleaf.context.IContext的對象,它把全部模板引擎執行須要的數據包含在一個Map變量中,同時引用用於處理外化文本的Locale。session

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} &gt; 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
 
  • HTML5友好的屬性及元素名
<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.Map(遍歷時取java.util.Map.Entry)、array、任何對象都被看成只有對象自身一個元素的列表java.util.Iterable、java.util.Map(遍歷時取java.util.Map.Entry)、array、任何對象都被看成只有對象自身一個元素的列表java.util.Map(遍歷時取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>
相關文章
相關標籤/搜索