前端渲染模板(一):Thymeleaf

1、使用

  本篇文章將以SpringBoot爲框架來介紹Thymeleaf的用法。javascript

  1 資源文件的約定目錄結構 css

Maven的資源文件目錄:/src/java/resources
spring-boot項目靜態文件目錄:/src/java/resources/static
spring-boot項目模板文件目錄:/src/java/resources/templates
spring-boot靜態首頁的支持,即index.html放在如下目錄結構會直接映射到應用的根目錄下:html

classpath:/META-INF/resources/index.html
classpath:/resources/index.html
classpath:/static/index.html
calsspath:/public/index.html 前端

  所以,SpringBoot默認的靜態資源文件應該放在resources/tatic下,而靜態頁面應該放在resources/templates文件夾下,這兩個文件不會自動建立,須要手動建立,以下圖所示:java

                                                                                                                              

  2 Maven依賴:jquery

1         <!-- thymeleaf 前端渲染模板依賴 -->
2         <dependency>
3             <groupId>org.springframework.boot</groupId>
4             <artifactId>spring-boot-starter-thymeleaf</artifactId>
5             <version>2.0.0.RELEASE</version>
6         </dependency>

  3 html頁面中(<html>標籤處):web

1 <html xmlns="http://www.w3.org/1999/xhtml"
2       xmlns:th="http://www.thymeleaf.org"
3       xmlns:sec="http://www.thymeleaf.org/thymeleaf-extras-springsecurity3">

  4 application.properties配置(application.yml則根據格式相應變化便可):spring

 1 # THYMELEAF (ThymeleafAutoConfiguration)  
 2 #開啓模板緩存(默認值:true)  
 3 spring.thymeleaf.cache=true   
 4 #Check that the template exists before rendering it.  
 5 spring.thymeleaf.check-template=true  
 6 #檢查模板位置是否正確(默認值:true)  
 7 spring.thymeleaf.check-template-location=true  
 8 #Content-Type的值(默認值:text/html)  
 9 spring.thymeleaf.content-type=text/html  
10 #開啓MVC Thymeleaf視圖解析(默認值:true)  
11 spring.thymeleaf.enabled=true  
12 #模板編碼  
13 spring.thymeleaf.encoding=UTF-8  
14 #要被排除在解析以外的視圖名稱列表,用逗號分隔  
15 spring.thymeleaf.excluded-view-names=  
16 #要運用於模板之上的模板模式。另見StandardTemplate-ModeHandlers(默認值:HTML5)  
17 spring.thymeleaf.mode=HTML5  
18 #在構建URL時添加到視圖名稱前的前綴(默認值:classpath:/templates/)  
19 spring.thymeleaf.prefix=classpath:/templates/  
20 #在構建URL時添加到視圖名稱後的後綴(默認值:.html)  
21 spring.thymeleaf.suffix=.html  
22 #Thymeleaf模板解析器在解析器鏈中的順序。默認狀況下,它排第一位。順序從1開始,只有在定義了額外的TemplateResolver Bean時才須要設置這個屬性。  
23 spring.thymeleaf.template-resolver-order=  
24 #可解析的視圖名稱列表,用逗號分隔  
25 spring.thymeleaf.view-names=  

  配置好以上的代碼,此時在html模板文件中動態的屬性使用th:命名空間修飾,就可使用Thymeleaf了。express

2、語法

  1 引用靜態資源文件:數組

    好比CSS和JS文件,語法格式爲「@{}」,如@{/js/blog/blog.js}會引入/static目錄下的/js/blog/blog.js文件。

  2 訪問spring-mvc中model的屬性:

    語法格式爲「${}」,如${user.id}能夠獲取model裏的user對象的id屬性,相似JSTL。

  3 循環:

    在html的標籤中,加入th:each=「value:${list}」形式的屬性,如<span th:each=」user:${users}」></span>能夠迭代users的數據

  4 判斷:    

在html標籤中,加入th:if=」表達式」能夠根據條件顯示html元素

1 <span th:if="${not #lists.isEmpty(blog.publishTime)}"> 
2   <span id="publishtime" th:text="${#dates.format(blog.publishTime, 'yyyy-MM-dd HH:mm:ss')}"></span> 
3 </span> 

以上代碼表示若blog.publishTime時間不爲空,則顯示時間。

5 時間格式化:

1 ${#dates.format(blog.publishTime,'yyyy-MM-dd HH:mm:ss')} //表示將時間格式化爲」yyyy-MM-dd HH:mm:ss」格式化寫法與Java格式化Date的寫法是一致的。 

  6 字符串拼接:

    有兩種形式 ,好比拼接這樣一個URL:/blog/delete/{blogId} 

第一種:th:href="'/blog/delete/' + ${blog.id }"
第二種:th:href="${'/blog/delete/' + blog.id }"

7 爲CSS樣式的某些路徑使用thyemleaf表達式:

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

   8 使用th:utext="@{}" 可讓變量裏面的html標籤被解析

3、表達式

  1 簡單表達式 (simple expressions)

1   ${...} 變量表達式
2 
3   *{...} 選擇變量表達式
4 
5   #{...} 消息表達式
6 
7   @{...} 連接url表達式

  2 字面量

1   'one text','another one!',... 文本
2 
3   0,34,3.0,12.3,... 數值
4 
5   true false 布爾類型
6 
7   null 空
8 
9   one,sometext,main 文本字符

  3 文本操做

1   + 字符串鏈接
2 
3   |The name is ${name}| 字符串鏈接

  4 算術運算

1   + , - , * , / , % 二元運算符
2 
3   - 負號(一元運算符)

  5 布爾操做

1   and,or 二元操做符
2 
3   !,not 非(一元操做符)

  6 關係操做符

1   > , < , >= , <= (gt , lt , ge , le)
2 
3   == , != (eq, ne)

  7 條件判斷

1 (if) ? (then) if-then
2 
3 (if) ? (then) : (else) if-then-else
4 
5 <tr th:class="${row.even}? 'even' : 'odd'">
6 ...
7 </tr>

條件表達式中的三個部分自身也能夠是表達式,也能夠是變量(${...}, *{...}), 消息(#{...}), URL (@{...}) 或字面量 ('...')
條件表達式也可使用括號來嵌套:

1 <tr th:class="${row.even}? (${row.first}? 'first' : 'even') : 'odd'">
2 ...
3 </tr>

  else表達式也能夠省略,當條件爲false時,會返回null:

1 <tr th:class="${row.even}? 'alt'">
2 ...
3 </tr>
4 (value) ?: (defaultvalue) Default

  只有在第一個表達式返回null時,第二個表達式纔會運算

  8 表達式工具對象

 1 #dates 與java.util.Date對象的方法對應,格式化、日期組件抽取等等
 2 #calendars 相似#dates,與java.util.Calendar對象對應
 3 #numbers 格式化數字對象的工具方法
 4 #strings 與java.lang.String對應的工具方法:contains、startsWith、prepending/appending等等
 5 #objects 用於對象的工具方法
 6 #bools 用於布爾運算的工具方法
 7 #arrays 用於數組的工具方法
 8 #lists 用於列表的工具方法
 9 #sets 用於set的工具方法
10 #maps 用於map的工具方法
11 #aggregates 用於建立數組或集合的聚合的工具方法
12 #messages 用於在變量表達式內部獲取外化消息的工具方法,與#{…}語法獲取的方式相同
13 #ids 用於處理可能重複出現(例如,做爲遍歷的結果)的id屬性的工具方法

  9 連接URL

URL在web模板中是一級重要元素,使用@{…}表示

URL的類型:

  絕對URL:

http://www.thymeleaf.org

  相對URL:

1 頁面相對: user/login.html
2 上下文相對:/itemdetails?id=3 (服務器上下文名稱會被自動添加)
3 服務器相對:~/billing/processInvoice(容許調用同一服務器上的另外一個上下文中的URL)
4 協議相對://code.jquery.com/jquery-2.0.3.min.js

Thymeleaf在任何狀況下均可以處理絕對URL,對於相對URL,則須要使用一個實現了IWebContext接口的上下文對象,這個對象包含了來自HTTP請求的信息,這些信息用於建立相對連接。

1 <!-- Will produce 'http://localhost:8080/gtvg/order/details?orderId=3' (plus rewriting) -->
2 <a href="details.html" th:href="@{http://localhost:8080/gtvg/order/details(orderId=${o.id})}">view</a>
3 
4 <!-- Will produce '/gtvg/order/details?orderId=3' (plus rewriting) -->
5 <a href="details.html" th:href="@{/order/details(orderId=${o.id})}">view</a>
6 
7 <!-- Will produce '/gtvg/order/3/details' (plus rewriting) -->
8 <a href="details.html" th:href="@{/order/{orderId}/details(orderId=${o.id})}">view</a>

  10 預處理
  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>

4、 設置屬性值

  1 th:attr 任何屬性值

1 <form action="subscribe.html" th:attr="action=@{/subscribe}">
2   <fieldset>
3     <input type="text" name="email" />
4     <input type="submit" value="Subscribe me!" th:attr="value=#{subscribe.submit}"/>
5   </fieldset>
6 </form>

  多個屬性一塊兒設置,用逗號隔開

<img src="../../images/gtvglogo.png" th:attr="src=@{/images/gtvglogo.png},title=#{logo},alt=#{logo}" />

  2 設置指定屬性

th:abbr
th:accept
th:accept-charset th:accesskey
th:action
th:align th:alt
th:archive
th:audio th:autocomplete
th:axis
th:background th:bgcolor
th:border
th:cellpadding th:cellspacing
th:challenge
th:charset th:cite
th:class
th:classid ...
1 <input type="submit" value="Subscribe me!" th:value="#{subscribe.submit}"/>
2 <form action="subscribe.html" th:action="@{/subscribe}">
3 <li><a href="product/list.html" th:href="@{/product/list}">Product List</a></li>

  設置多個屬性在同一時間 有兩個特殊的屬性能夠這樣設置: th:alt-title 和 th:lang-xmllang

th:alt-title 設置 alt 和 title
th:lang-xmllang 設置 lang 和 xml:lang

1 <img src="../../images/gtvglogo.png" th:attr="src=@{/images/gtvglogo.png},title=#{logo},alt=#{logo}" />
2 
3 <img src="../../images/gtvglogo.png"th:src="@{/images/gtvglogo.png}" th:title="#{logo}" th:alt="#{logo}" />
4 
5 <img src="../../images/gtvglogo.png"th:src="@{/images/gtvglogo.png}" th:alt-title="#{logo}" />

  前置和後置添加屬性值 th:attrappend 和 th:attrprepend

<input type="button" value="Do it!" class="btn" th:attrappend="class=${' ' + cssStyle}" />

  編譯後:

<input type="button" value="Do it!" class="btn warning" />

  還有兩個特定的添加屬性 th:classappend 和 th:styleappend

<tr th:each="prod : ${prods}" class="row" th:classappend="${prodStat.odd}? 'odd'">

  3 修復的布爾屬性

<input type="checkbox" name="active" th:checked="${user.active}" />

  全部修復的布爾屬性:

th:async 
th:autofocus
th:autoplay
th:checked
th:controls
th:declare
th:default
th:defer
th:disabled
th:formnovalidate
th:hidden
th:ismap
th:loop
th:multiple
th:novalidate
th:nowrap
th:open
th:pubdate
th:readonly
th:required
th:reversed
th:scoped
th:seamless
th:selected

  HTML5友好的屬性及元素名

1 <table>
2 <tr data-th-each="user : ${users}">
3 <td data-th-text="${user.login}">...</td>
4 <td data-th-text="${user.name}">...</td>
5 </tr>
6 </table>

  注:data-{prefix}-{name}是編寫HTML5自定義屬性的標準語法,不須要開發者使用th:*這樣的命名空間,Thymeleaf讓這種語法自動對全部dialect均可用。

5、遍歷

  1 基礎

1 <tr th:each="prod : ${prods}">
2   <td th:text="${prod.name}">Onions</td>
3   <td th:text="${prod.price}">2.41</td>
4   <td th:text="${prod.inStock}? #{true} : #{false}">yes</td>
5 </tr>

  可遍歷的對象:實現java.util.Iterable、java.util.Map(遍歷時取java.util.Map.Entry)、array、任何對象都被看成只有對象自身一個元素的列表

  2 狀態

當前遍歷索引,從0開始,index屬性
當前遍歷索引,從1開始,count屬性
總元素數量,size屬性
每一次遍歷的iter變量,current屬性
當前遍歷是even仍是odd,even/odd布爾屬性
當前遍歷是第一個,first布爾屬性
當前遍歷是最後一個,last布爾屬性

1 <tr th:each="prod,iterStat : ${prods}" th:class="${iterStat.odd}? 'odd'">
2   <td th:text="${prod.name}">Onions</td>
3   <td th:text="${prod.price}">2.41</td>
4   <td th:text="${prod.inStock}? #{true} : #{false}">yes</td>
5 </tr>

若不指定狀態變量,Thymeleaf會默認生成一個名爲「變量名Stat」的狀態變量:

1 <tr th:each="prod : ${prods}" th:class="${prodStat.odd}? 'odd'">
2   <td th:text="${prod.name}">Onions</td>
3   <td th:text="${prod.price}">2.41</td>
4   <td th:text="${prod.inStock}? #{true} : #{false}">yes</td>
5 </tr>

6、條件運算

1 <tr th:each="prod : ${prods}" th:class="${prodStat.odd}? 'odd'">
2   <td th:text="${prod.name}">Onions</td>
3   <td th:text="${prod.price}">2.41</td>
4   <td th:text="${prod.inStock}? #{true} : #{false}">yes</td>
5   <td>
6     <span th:text="${#lists.size(prod.comments)}">2</span> comment/s
7     <a href="comments.html" th:href="@{/product/comments(prodId=${prod.id})}" th:if="${not #lists.isEmpty(prod.comments)}">view</a>
8   </td>
9 </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

  th:if的反面是th:unless

 1 <a href="comments.html" th:href="@{/comments(prodId=${prod.id})}" th:unless="${#lists.isEmpty(prod.comments)}">view</a>
 2 th:switch 和 th:case
 3 
 4 <div th:switch="${user.role}">
 5   <p th:case="'admin'">User is an administrator</p>
 6   <p th:case="#{roles.manager}">User is a manager</p>
 7 </div>
 8 
 9 <div th:switch="${user.role}">
10   <p th:case="'admin'">User is an administrator</p>
11   <p th:case="#{roles.manager}">User is a manager</p>
12   <p th:case="*">User is some other thing</p>
13 </div>

7、坑

  總結一下在使用過程當中遇到的坑:

  1 獲取項目根目錄,不少時候咱們都須要獲取本項目的根目錄,可是使用的代碼是如下代碼才能得到:

<script th:inline="javascript" type="text/javascript">
    var ctx=[[${#httpServletRequest.getContextPath()}]];
</script>

   注意以上代碼,若是須要在自定義的javascript中使用thymeleaf表達式,則須要將script聲明一下:th:inline="javascript"。

  2 獲取圖片路徑,當咱們使用thymeleaf的時候必定要注意單、雙引號的區別,否則是沒法獲取到對應的值或者路徑的:

<span class="img" th:style="'background-image: url('+@{/images/news/}+${top4News[2].originArticleId}+'/1.jpg'+');'"></span>

   請注意以上代碼:當咱們要在backgroud-image這個標籤下引用對應路徑的img時:

    首先使用th:style進行修飾。

    而後在background-image標籤先後必定要加單引號,不然不會起做用:

'background-image:xxx'

     接着就是在url裏面拼接你的img路徑,請注意url('xxx'),也有單引號!

    最後才能經過此路徑獲取到相應的圖片。

8、總結

  在使用thymeleaf的過程當中,遇到了一些坑,但願你們在這樣的坑中少走一些彎路。

相關文章
相關標籤/搜索