1. 程式人生 > >thymeleaf學習總結

thymeleaf學習總結

.介紹

1.什麼是thymeleaf

Thymeleaf是現代化伺服器端的Java頁面模板引擎,不同於JSP和FreeMarker,Thymeleaf的語法更加接近HTML,

 

2.為什麼使用thymeleaf

springboot官方的支援與推薦

Spring Boot為以下的模板引擎提供自動配置支援:

1.FreeMarker

2.Groovy

3.Thymeleaf

4.Velocity(1.4已不再支援)

5.Mustache

 

 

注:由於在內嵌servlet容器中使用JSPs存在一些已知的限制,所以建議儘量不使用它們。

使用以上引擎中的任何一種,並採用預設配置,則模組會從 src/main/resources/templates 自動載入。

 

引用:Spring Boot參考指南

 

 

ThymeLeaf是一個健康的開源專案:每個月都有新的特性、良好的文件、響應性的使用者論壇

如果您希望web設計器能夠讀取檢視檔案,那麼它是理想的模板引擎。所使用的表示式語言(實際上稱為標準方言)比JSP表示式語言強大得多。與JSP不同,Thymeleaf適用於富HTML電子郵件(參見http://www.thymeleaf.org/springmail.html

).

 

引用:SpringMVC:從JSP和Tiles到Thymeleaf

 

 

3.怎麼使用

<html xmlns:th="http://www.thymeleaf.org">

 

 

 

 

本文側重點是總結和講解thymeleaf的常用標籤,表示式及表示式物件的使用

 

二.常用標籤的用法

 

th:text 

th:text 用於文字的顯示,並且可以進行簡單的計算。

<td  th:text="${username}">mlm</td> -> <td>maliming</td>

<td  th:text="9+7">2018</td> -> <td>16</td>

 

th:utext

th:utext 用於html的文字替換,常用於富文字編輯器編輯後的內容顯示到前臺頁面上。

<p th:utext="${article.content}"></p> -> <p>my name is <b>maliming</b></p>

 

th:if

th:if 用於判斷條件,還可以多條件 and,or(二元操作符),!,not非(一元操作符)。

<div th:if="${user} != null">show</div>如果user物件為空則不顯示,不為空則顯示 -> <div>show</div>

 

<div th:if="${user} != null and ${otherUser} != null">show</div> 

 

不能用"<",">"等符號,要用"lt"等替代

 

運算子還可以寫在${}裡<div th:if="${user.number > 100}">show</div> -> <div>show</div> 運算子放在了 {} 內部, 此時整個 {} 內的表示式用 ognl/spel 引擎計算; 如果運算子放在外部, 那麼 thymeleaf 引擎負責計算。

 

運算子擴充套件

進位制運算子:+,-,\*,/,%

負號:-

二進位制運算子:and 、or

布林否定:!,not

比較運算子:>,<,> =,<=(gt,lt,ge,le)

相等運算子:==,!=(eq,ne)

字串連線:+

文字替換:|The name is ${name}|

條件運算子:

   If-then:\(if\) ? \(then\)

   If-then-else:\(if\) ? \(then\) : \(else\)

   Default:\(value\) ?: \(defaultvalue\)

 

 

 

 

th:unless

 th:unless 用於判斷條件,與th:if作用相反。

<div th:if="${user} != null">show</div>如果user物件不為空則不顯示,為空則顯示 -> <div>show</div> 

 

 

 

th:switch th:case

th:switch th:case 用於多個同等級相同目的判斷,多選一時使用。

<div th:switch="${user.name}">

 

    <p th:case="maliming">first</p>若${user.name}中的值為maliming則顯示,否則不顯示

 

    <p th:case="${otherUser.name}">second</p>

 

</div>

 

 

 

th:action

th:action 用於定義後臺控制器的路徑,表單的提交地址,相當於<form>標籤的action屬性。

<form th:action="@{user/login}" method="post"></form>

 

 

 

th:each

th:each 用於遍歷集合中的物件,相當於jstl中的<c:forEach>標籤。

List集合迴圈遍歷

 

<tr th:each="user,userStat:${messages.list}">

    <td th:text="${user.name}"></td>

    <td th:text="userStat.index"></td>

</tr>

 

其中的user是臨時變數,相當於for(User user : users)中的user,userStat稱為狀態變數,屬性有index:當前迭代物件的index(從0開始計算),count: 當前迭代物件的index(從1開始計算), size:被迭代物件的大小,current:當前迭代變數,even/odd:布林值,當前迴圈是否是偶數/奇數(從0開始計算), first:布林值,當前迴圈是否是第一個,last:布林值,當前迴圈是否是最後一個。

 

Map集合迴圈遍歷

<div th:each="map:${maps}" th:text="${map}"></div>

陣列迴圈遍歷

<tr>

    <td th:each="array:${arrays}" th:text="${array}"></td>

</tr>

 

 

th:value

 th:value 用於屬性賦值。

<option th:value="${user.name}"></option> -> <option value="maliming"></option>

 

 

th:src

th:src 用於外部資源的引入,例如圖片,js檔案。

<img th:src="@{../images/myself.jpg}"/>或<script th:src="@{../static/login.js}"></script>

 

 

th:href

th:href 用於定義超連結,相當於<a></a>標籤的href屬性。

<a th:href="@{/user/selectUser?(currentPage=1,reTypeid=${reTypeid},inquiry=${inquiry})}"></a> 傳參。

 

 

th:remove

th:remove 用於刪除。可以表示式傳參。

<table border="1">  

    <thead>  

          <tr>  

             <th>編號</th>  

             <th>使用者名稱</th>    

             <th>姓名</th>   

             <th>性別</th>  

          </tr>  

    </thead>  

    <tbody th:remove="all-but-first" 或者表示式th:remove="${choice}? all : all-but-first">  

          <tr>  

             <td>1</td>  

             <td>[email protected]</td>  

             <td>Tom</td>  

             <td>男</td>  

          </tr>  

          <tr>  

             <td>3</td>  

             <td>[email protected]</td>  

             <td>Lucy13</td>  

             <td>女</td>  

           </tr>  

     </tbody>

</table>  

 

 

這裡的<tbody></tbody>標籤中有th:remove="all-but-first",意思是隻保留<tbody></tbody>標籤中的第一個字標籤,也就是name為Tom的所在<tr></tr>,其他的子標籤則會刪除,th:remove有五個屬性值。

all:刪除所在標籤和內容及其所屬的所有子標籤。body:刪除所在標籤的內容及其所屬的所有子標籤。tag:刪除所在標籤,不刪除任何所屬的子標籤。all-but-first:刪除除第一個子標籤外的其他子標籤。none:不起作用,什麼也不做。

th:selected

th:selected 用於選擇框設定選中值。通常和th:each一起使用。

<select

    <option th:selected="${user.name} == ${otherUser.name}"></option> 若相等就預設選<option></option>

 

</select>

 

 

 

 

th:object

1.13 th:object 用於表單資料物件繫結,後臺controller中引數保持一致,和選擇(星號)表示式。

<form th:object="${user}">

    <input th:value="*{name}"/> *號代替了${user}

</form>

public ModelAndView addUser(@RequestParam(value = "user") User user,ModelMap model){}

 

 

 

 

th:attr

th:attr 用於設定任意屬性

<input th:attr="value=${user.name}"/> 設定單個屬性。

<input th:attr="value=${user.username},name=username"/> 設定多個屬性之間用逗號隔開。

 

 

th:fragment

在我們的模板中,我們經常希望從其他模板中包含某些部分,如頁尾,頁首,選單等部分

為了做到這一點,Thymeleaf需要我們定義這些部分“片段”,以供其他模版包含,可以使用th:fragment屬性來定義被包含的模版片段。

<!DOCTYPE html>

<html xmlns:th="http://www.thymeleaf.org">

<body>

<div th:fragment="copy">

© 2011 The Good Thymes Virtual Grocery

</div>

</body>

</html>

上面的程式碼定義了一個名為copy的片段,我們可以使用th:insert或th:replace屬性(以及th:include,儘管Thymeleaf 3.0不再推薦使用它),容易地包含在我們的主頁中:

<body>

...

<div th:insert="~{footer :: copy}"></div>

</body>

 

 

請注意,th:insert期望一個片段表示式(〜{...})。 在上面的例子中,這是一個簡單的片段表示式,(〜{,})包圍是完全可選的,所以上面的程式碼將等價於:

<body>

...

<div th:insert="footer :: copy"></div>

</body>

fragment載入語法如下:

templatename::selector:”::”前面是模板檔名,後面是選擇器

::selector:只寫選擇器,這裡指fragment名稱,則載入本頁面對應的fragment

templatename:只寫模板檔名,則載入整個頁面

 

模板名和選擇器都可以是表示式(甚至是條件表示式!)

<div th:insert="footer :: (${user.isAdmin}? #{footer.admin} : #{footer.normaluser})"></div>

也可以使用th:replace

th:insert和th:replace(th:include)之間的區別

th:insert和th:replace之間有什麼區別?(th:include在3.0之後不推薦使用了)?

th:insert是最簡單的:它將簡單地插入指定宿主標籤的標籤體中。

th:replace實際上用指定的片段替換其宿主標籤。替換當前標籤為模板中的標籤,載入的節點會整個替換掉載入他的div

th:include類似於th:insert,⽽而不是插入片段,它只插入此片段的內容。

 

可引數化的片段簽名

為了使模板片段具有多類似函式的功能,用th:fragment定義的片段可以指定一組引數:

<div th:fragment="frag (onevar,twovar)">

<p th:text="${onevar} + ' - ' + ${twovar}">...</p>

</div>

可以通過以下兩種語法中的一種來引用上述模版⽚段,下面的th:replace改成th:insert也是一樣的:

<div th:replace="::frag (${value1},${value2})">...</div>

<div th:replace="::frag (onevar=${value1},twovar=${value2})">...</div>

 

不帶段引數的段區域性變數

即使片段沒有定義引數:

<div th:fragment="frag">

...

</div>

 

 

我們可以使用上面指定的第二個語法來呼叫它們(只有第二個語法才可以):

<div th:replace="::frag (onevar=${value1},twovar=${value2})">

 

上面的程式碼等價於th:replace和th:with的組合:

<div th:replace="::frag" th:with="onevar=${value1},twovar=${value2}">

 

請注意,片段的區域性變數規範 - 無論是否具有引數簽名 - 都不會導致上下

文在執行之前被清空。片段仍然能夠訪問呼叫模板中正在使用的每個上下文變數。

由於片段表示式的強大功能,我們不僅可以為片段指定文字型別,數字型別,bean物件型別的引數,還可以指定標記片段作為引數。

這允許我們以一種方式建立我們的片段,使得它們可以呼叫戶模板的標記,從而產生非常靈活的模板佈局機制。

請注意在下面的片段中使用標題和連結變數:

<head th:fragment="common_header(title,links)">

<title th:replace="${title}">The awesome application</title>

 

<!-- Common styles and scripts -->

<link rel="stylesheet" type="text/css" media="all" th:href="@{/css/awesomeapp.css}">

<link rel="shortcut icon" th:href="@{/images/favicon.ico}">

<script type="text/javascript" th:src="@{/sh/scripts/codebase.js}"></script>

 

<!--/* Per-page placeholder for additional links */-->

<th:block th:replace="${links}" />

</head>

 

我們現在呼叫這個片段:

<head th:replace="base :: common_header(~{::title},~{::link})">

<title>Awesome - Main</title>

<link rel="stylesheet" th:href="@{/css/bootstrap.min.css}">

<link rel="stylesheet" th:href="@{/themes/smoothness/jquery-ui.css}">

</head>

 

結果將使用呼叫模板中的實際<title>和<link>標籤作為標題和連結變數的值,導致我們的⽚段在插入期間被定製化:

<head>

<title>Awesome - Main</title>

<!-- Common styles and scripts -->

<link rel="stylesheet" type="text/css" media="all" href="/awe/css/awesomeapp.css">

<link rel="shortcut icon" href="/awe/images/favicon.ico">

<script type="text/javascript" src="/awe/sh/scripts/codebase.js"></script>

<link rel="stylesheet" href="/awe/css/bootstrap.min.css">

<link rel="stylesheet" href="/awe/themes/smoothness/jquery-ui.css">

</head>

 

 

 

th:block

Thymeleaf標準方言中唯一的元素處理器(不是屬性)是:th:block。

th:block是一個只允許模板開發人員指定他們想要的屬性的屬性容器。

Thymeleaf將執行這些屬性,然後簡單地製作塊。

所以它可能是有用的,例如,當為每個元素建立多個<tr>的迭代表時:

<table>

  <th:block th:each="user : ${users}">

    <tr>

        <td th:text="${user.login}">...</td>

        <td th:text="${user.name}">...</td>

    </tr>

    <tr>

        <td colspan="2" th:text="${user.address}">...</td>

    </tr>

  </th:block>

</table>

 

 

 

 

th:inline

Thymeleaf模板中的三個模板被認為是問本:TEXT,JAVASCRIPT和CSS。 這將它們與標記模板模式區分開來:HTML和XML。

文字模板模式和標記模式之間的關鍵區別在於,在文字模板中,沒有標籤以屬性的形式插⼊邏輯,因此我們必須依賴其他機制。最基本的機制是內聯, 內聯語法是以文字模板模式輸出表達式結果的最簡單方法,因此郵件形式模板來說,內聯是最好的機制。

內聯文字

<p th:inline="text">Hello, [[#{test}]]</p>

 

內聯JavaScript

<script th:inline="javascript">

    ...

    var username = [[${session.user.name}]];

    ...

</script>

 

內聯CSS

Thymeleaf還允許在CSS <style>標籤中使⽤內聯,如:

 

<style th:inline="css">

  ...

</style>

 

例如,假設我們有兩個變數設定為兩個不同的String值:

classname = 'main elems'

align = 'center'

我們可以這樣做:

<style th:inline="css">

    .[[${classname}]] {

      text-align: [[${align}]];

    }

</style>

輸出結果如下:

<style th:inline="css">

    .main\ elems {

      text-align: center;

    }

</style>

 

 

 

 

 

 

三.表示式

變量表達式:$ {...}

 

選擇變量表達式:* {...}

 

訊息表示式:#{...}

 

連結網址表示式:@ {...}

 

片段表示式:〜{...}

 

變量表達式 ${}

<input type="text" name="userName" value="James Carrot" th:value="${user.name}" />

上述程式碼為引用user物件的name屬性值

 

 

選擇表示式*{}

我們不僅可以將變量表達式寫為$ {...},還可以作為* {...}。

這兩種方式有一個重要的區別:星號語法計算所選物件而不是整個上下⽂

的表示式。 也就是說,只要沒有選定的物件,$和*語法就會完全相同。

什麼是選定物件? 使用th:object屬性的表示式的結果。 我們在使用者個⼈

資料(userprofile.html)頁面中使用一個:

 <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}">Sebas

tian</span>.</p>

  <p>Surname: <span th:text="${session.user.lastName}">Pep

per</span>.</p>

  <p>Nationality: <span th:text="${session.user.nationalit

y}">Saturn</span>.</p>

</div>

 

選擇表示式一般跟在th:object後,直接取object中的屬性

 

URL表示式 @{}

 

<a href="details.html" th:href="@{/order/details(orderId=${o.id})}">view</a>

@{... ...}支援決定路徑和相對路徑。其中相對路徑又支援跨上下文呼叫url和協議的引用

當URL為後臺傳出的引數時,程式碼如下:

 

<img src="../../static/assets/images/qr-code.jpg" th:src="@{${path}}" alt="二維碼" />

 

片段表示式〜{}

程式碼片段表示式是表示標記片段的簡單方法,並將其移動到模板周圍。

這允許我們複製它們,將它們傳遞給其他模板作為引數,等等。

最常用的用法是使⽤th:insert或th:replace進行片段插入:

<div th:insert="~{commons :: main}">...</div>

 

它們可以在任何地方使用,就像任何其他變數一樣:

<div th:with="frag=~{footer :: #main/text()}">

  <p th:insert="${frag}">

</div>

 

 

 

 

文字國際化表示式 #{}

 

<p th:utext="#{home.welcome}">Welcome to our grocery store!</p>

呼叫國際化的welcome語句,國際化資原始檔如下

resource_en_US.properties:home.welcome=Welcome to here!

resource_zh_CN.properties:home.welcome=歡迎您的到來!

 

 

 

 

 

四.表示式物件

我們已經提到$ {...}表示式實際上是在上下中包含的變數的對映上執的OGNL(Object-Graph Navigation Language)物件

${} 中預存物件(表示式中基本物件)

 

基本表示式物件

當對上下文變數計算OGNL表示式時,某些物件可用於表示式以獲得更高的靈活性。 這些物件將被引用(按照OGNL標準),從#符號開始(請注意,這些物件不是Map集合/名稱空間):

 

#ctx:上下文物件。

#locale:上下文區域設定。

#vars:上下文變數。

#request :(僅在Web Contexts中)HttpServletRequest物件。

#session :(僅在Web上下文中)HttpSession物件。

#servletContext :(僅在Web上下文中)ServletContext物件。

#response:(僅在Web上下文中)HttpServletResponse物件。

 

#ctx:上下文物件。 根據我們的環境(獨立環境或Web環境),實現org.thymeleaf.context.IContext或org.thymeleaf.context.IWebContext。

${#ctx.locale}

${#ctx.variableNames}

${#ctx.request}

${#ctx.response}

${#ctx.session}

${#ctx.servletContext}

 

#locale:直接訪問與當前請求關聯的java.util.Locale。 ${#locale}

...

#request:直接訪問與當前請求關聯的javax.servlet.http.HttpServletRequest物件。

${#request.getAttribute('foo')}

${#request.getParameter('foo')}

${#request.getContextPath()}

${#request.getRequestName()}

 

 

#session:直接訪問與當前請求關聯的javax.servlet.http.HttpSession物件。

${#session.getAttribute('foo')}

${#session.id}

${#session.lastAccessedTime}

...

 

#servletContext:直接訪問與當前請求關聯的javax.servlet.ServletContext物件。

${#servletContext.getAttribute('foo')}

${#servletContext.contextPath}

...

 

 

 

request和session屬性的web名稱空間

在Web環境中使用Thymeleaf時,我們可以使用一系列快捷方式來訪問請求引數,會話屬性和應用程式屬性:

注意:這些不是上下文物件,而是新增到上下文中的Map集合作為變數,所以我們在沒有#的情況下訪問它們。 在某種程度上,它們作為名稱空間。

 

param:用於獲取請求引數。 $ {param.foo}是一個帶有foo請求引數值的String [],所以$ {param.foo [0]}通常用於獲取第一個值。

 

${param.foo}     // Retrieves a String[] with the values of request parameter 'foo'

${param.size()}

${param.isEmpty()}

${param.containsKey('foo')}

...

session:用於獲取session屬性。

${session.foo}

...

application:用於獲取應用程式或servlet上下文屬性。

${application.foo}

...

 

 

 

 

 

工具表示式物件

除了這些基本的物件之外,Thymeleaf將為我們提供一組工具物件,這些物件將幫助我們在表示式中執行常見任務。

#execInfo:有關正在處理的模板的資訊。

#messages:用於在變量表達式中獲取外部化訊息的方法,與使用

#{...}語法獲得的方式相同,操作訊息的工具。

#uris:轉義URL / URI部分的方法

#conversions:執行配置的轉換服務(如果有的話)的方法。

#dates:java.util.Date物件的方法:格式化,元件提取等

#calendars:類似於#dates,但對於java.util.Calendar物件。

#numbers:用於格式化數字物件的方法。

#strings:String物件的⽅法:contains,startsWith,prepending /appending等

#objects:一般物件的方法,參照java.lang.Object;

#bools:判斷布林型別工具。

#arrays:陣列操作的工具;

#lists:列表操作的工具,參照java.util.List;

#sets:Set操作工具,參照java.util.Set;

#maps:Map操作工具,參照java.util.Map;

#aggregates:運算元組或集合的工具;

#ids:處理可能重複的id屬性的方法(例如,作為迭代的結果)。

 

 

例子:

簡單資料轉換(數字,日期)

<dt>價格</dt>

<dd th:text="${#numbers.formatDecimal(product.price, 1, 2)}">180</dd>

<dt>進貨日期</dt>

<dd th:text="${#dates.format(product.availableFrom, 'yyyy-MM-dd')}">2014-12-01</dd>

字串拼接

<dd th:text="${'$'+product.price}">235</dd>

 

 

原文:https://blog.csdn.net/malimingwq/article/details/79329921

 

 

 

五.其他

驗證模板的正確性

<!DOCTYPE html SYSTEM "http://www.thymeleaf.org/dtd/xhtml1-strict-thymeleaf-4.dtd">

<!DOCTYPE html SYSTEM "http://www.thymeleaf.org/dtd/xhtml1-transitional-thymeleaf-4.dtd">

<!DOCTYPE html SYSTEM "http://www.thymeleaf.org/dtd/xhtml1-frameset-thymeleaf-4.dtd">

<!DOCTYPE html SYSTEM "http://www.thymeleaf.org/dtd/xhtml11-thymeleaf-4.dtd">

 

靜態資源引入問題

可直接在static資料夾下的css資料夾和js資料夾引用

<link th:href="@{/css/style.css}"  rel="stylesheet" />

<script th:src="@{/js/jquery-2.1.4.min.js}"></script>

也可以設定一個字首

spring:

  mvc:

    static-path-pattern: /static/**

 

引用:

<link th:href="@{/static/css/style.css}"  rel="stylesheet" />

<script th:src="@{/static/js/jquery-2.1.4.min.js}"></script>

 

 

 

 

 

結語

thymeleaf 對前端來講確實是個好東西,前後端協作更方便,但是貌似如果改成完全的前後分離的模式,這些模板引擎就都用不到了,前端就是原生html+css+js,非同步請求後端資料填充頁面。完全的前後分離,總感覺這樣做會更頻繁的http請求後臺,也有不太好的地方,Thymeleaf 反而是折中的方案了。從半分離到完全分離過渡。依產品而定吧,有些業務不適合分離。