一、概述
1.是什么
簡單說, Thymeleaf 是一個跟 Velocity、FreeMarker 類似的模板引擎,它可以完全替代 JSP 。
2.feature
1.Thymeleaf 在有網絡和無網絡的環境下皆可運行,即它可以讓美工在瀏覽器查看頁面的靜態效果,也可以讓程序員在服務器查看帶數據的動態頁面效果。這是由於它支持 html 原型,然后在 html 標簽里增加額外的屬性來達到模板+數據的展示方式。瀏覽器解釋 html 時會忽略未定義的標簽屬性,所以 thymeleaf 的模板可以靜態地運行;當有數據返回到頁面時,Thymeleaf 標簽會動態地替換掉靜態內容,使頁面動態顯示。
2.Thymeleaf 開箱即用的特性。它提供標准和spring標准兩種方言,可以直接套用模板實現JSTL、 OGNL表達式效果,避免每天套模板、該jstl、改標簽的困擾。同時開發人員也可以擴展和創建自定義的方言。3. Thymeleaf 提供spring標准方言和一個與 SpringMVC 完美集成的可選模塊,可以快速的實現表單綁定、屬性編輯器、國際化等功能。
3.文檔
官方教程:http://www.thymeleaf.org/doc/tutorials/2.1/usingthymeleaf.html#what-is-thymeleaf
推薦教程:http://blog.didispace.com/springbootweb/
http://blog.csdn.net/u012706811/article/details/52185345
二、HelloWorld
1.引入依賴
springboot直接引入:
1 <dependency> 2 <groupId>org.springframework.boot</groupId> 3 <artifactId>spring-boot-starter-thymeleaf</artifactId> 4 </dependency>
非springboot項目使用如下依賴:
<dependency> <groupId>org.thymeleaf</groupId> <artifactId>thymeleaf</artifactId> <version>2.1.4</version> </dependency>
默認的模板映射路徑是:src/main/resources/templates,
springboot1.4之后,可以使用thymeleaf3來提高效率,並且解決標簽閉合問題,配置方式
<properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <!-- set thymeleaf version --> <thymeleaf.version>3.0.0.RELEASE</thymeleaf.version> <thymeleaf-layout-dialect.version>2.0.0</thymeleaf-layout-dialect.version> <!--set java version--> <java.version>1.8</java.version> </properties>
之前的model/modelMap/modelAndView等頁面數據傳遞參考之前隨筆:點擊查看
快速回顧:
package com.learndemo.controller; import java.util.HashMap; import java.util.Map; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.ui.ModelMap; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.servlet.ModelAndView; @Controller @RequestMapping(value = "/return") public class LearnReturnType { /** * Model本身不能設置頁面跳轉的url地址別名或者物理跳轉地址,那么我們可以通過控制器方法的返回值來設置跳轉url * 地址別名或者物理跳轉地址 * * @param model * 一個接口, 其實現類為ExtendedModelMap,繼承了ModelMap類 * @return 跳轉url地址別名或者物理跳轉地址 */ @RequestMapping(value = "/index1") public String index1(Model model) { model.addAttribute("result", "后台返回index1"); return "result"; } /** * ModelMap對象主要用於傳遞控制方法處理數據到結果頁面,類似於request對象的setAttribute方法的作用。 用法等同於Model * * @param model * @return 跳轉url地址別名或者物理跳轉地址 */ @RequestMapping(value = "/index2") public String index2(ModelMap model) { model.addAttribute("result", "后台返回index2"); return "result"; } /** * ModelAndView主要有兩個作用 設置轉向地址和傳遞控制方法處理結果數據到結果頁面 * @return 返回一個模板視圖對象 */ @RequestMapping(value = "/index3") public ModelAndView index3() { ModelAndView mv = new ModelAndView("result"); // ModelAndView mv = new ModelAndView(); // mv.setViewName("result"); mv.addObject("result", "后台返回index3"); return mv; } /** * map用來存儲遞控制方法處理結果數據,通過ModelAndView方法返回。 * 當然Model,ModelMap也可以通過這種方法返回 * @return 返回一個模板視圖對象 */ @RequestMapping(value = "/index4") public ModelAndView index4() { Map<String, String> map = new HashMap<String, String>(); map.put("result", "后台返回index4"); return new ModelAndView("result", map); } } model/modelMap/modelAndView
2.配置thymeleaf視圖解析器
這點與springMVC是相類似的:
#thymeleaf start spring.thymeleaf.mode=HTML5 spring.thymeleaf.encoding=UTF-8 spring.thymeleaf.content-type=text/html #開發時關閉緩存,不然沒法看到實時頁面 spring.thymeleaf.cache=false #thymeleaf end
實際項目中可能會有不太嚴格的HTML格式,此時設置mode=HTML5將會對非嚴格的報錯,可以參考以下配置:
spring.thymeleaf.mode=LEGACYHTML5
你可能會發現在默認配置下,thymeleaf對.html的內容要求很嚴格,比如<meta charset="UTF-8" />, 如果少最后的標簽封閉符號/,就會報錯而轉到錯誤頁。也比如你在使用Vue.js這樣的庫,然后有<div v-cloak></div>這樣的html代碼, 也會被thymeleaf認為不符合要求而拋出錯誤。 因此,建議增加下面這段: spring.thymeleaf.mode = LEGACYHTML5 spring.thymeleaf.mode的默認值是HTML5,其實是一個很嚴格的檢查,改為LEGACYHTML5可以得到一個可能更友好親切的格式要求。 需要注意的是,LEGACYHTML5需要搭配一個額外的庫NekoHTML才可用。 <dependency> <groupId>net.sourceforge.nekohtml</groupId> <artifactId>nekohtml</artifactId> <version>1.9.22</version> </dependency> 最后重啟項目就可以感受到不那么嚴格的thymeleaf了。
這樣,需要的配置項如下:
# 一項是非嚴格的HTML檢查,一項是禁用緩存來獲取實時頁面數據,其他采用默認項即可 thymeleaf: mode: LEGACYHTML5 cache: false
// 完整配置項參考類ThymeleafProperties
3。編寫控制器
/** * 測試demo的controller * * @author zcc ON 2018/2/8 **/ @Controller public class HelloController { private static final Logger log = LoggerFactory.getLogger(HelloController.class); @GetMapping(value = "/hello") public String hello(Model model) { String name = "jiangbei"; model.addAttribute("name", name); return "hello"; } }
4.編寫模板html
<!DOCTYPE HTML> <html xmlns:th="http://www.thymeleaf.org"> <head> <title>hello</title> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/> </head> <body> <!--/*@thymesVar id="name" type="java.lang.String"*/--> <p th:text="'Hello!, ' + ${name} + '!'">3333</p> </body> </html>
其中,注釋是通過alt+enter進行自動生成的,便於IDEA補全,如果不加,IDEA將會報錯cannot reslove,
當然也可以通過如下方式解決,解決之前推薦在maven項目中reimport一下!(據說新版本的IDEA中已經修復此問題,待更新至2017.3以后)
5.測試
三、基礎語法
1.創建HTML
由上文也可以知道需要在html中添加:
<html xmlns:th="http://www.thymeleaf.org">
這樣,下文才能正確使用th:*形式的標簽!
2.獲取變量值${...}
通過${…}進行取值,這點和ONGL表達式語法一致!
<!--/*@thymesVar id="name" type="java.lang.String"*/--> <p th:text="'Hello!, ' + ${name} + '!'">3333</p>
選擇變量表達式*{...}
<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>
至於p里面的原有的值只是為了給前端開發時做展示用的.這樣的話很好的做到了前后端分離。
這也是Thymeleaf非常好的一個特性:在無網絡的情況下也能運行,也就是完全可以前端先寫出頁面,模擬數據展現效果,后端人員再拿此模板修改即可!
3.鏈接表達式: @{…}
用來配合link src href使用的語法,類似的標簽有: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> <a href="details.html" th:href="@{order/{orderId}/details(orderId=${o.id})}">Content路徑,默認訪問static下的order文件夾</a>
4.文本替換
<span th:text="'Welcome to our application, ' + ${user.name} + '!'">
或者下面的表達方式:(只能包含表達式變量,而不能有條件判斷等!)
<span th:text="|Welcome to our application, ${user.name}!|">
5.運算符
數學運算
- 二元操作:+, - , * , / , %
- 一元操作: - (負)
邏輯運算
- 一元 : and or
- 二元 : !,not
比較運算(為避免轉義尷尬,可以使用括號中的英文進行比較運算!)
- 比較:> , < , >= , <= ( gt , lt , ge , le )
- 等於:== , != ( eq , ne )
條件運算
- If-then: (if) ? (then)
- If-then-else: (if) ? (then) : (else)
- Default: (value) ?: (defaultvalue)
'User is of type ' + (${user.isAdmin()} ? 'Administrator' : (${user.type} ?: 'Unknown'))
6.條件
if/unless
使用th:if和th:unless屬性進行條件判斷,th:unless於th:if恰好相反,只有表達式中的條件不成立,才會顯示其內容。
<a th:href="@{/login}" th:unless=${session.user != null}>Login</a>
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> <p th:case="*">User is some other thing</p> </div>
7.循環
通過th:each
<!DOCTYPE HTML>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<title>hello</title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
</head>
<body>
<!-- 不存在則忽略,顯示hello null!(可以通過默認值進行設置)-->
<p th:text="'Hello ' + (${name}?:'admin')">3333</p>
<table>
<tr>
<th>ID</th>
<th>NAME</th>
<th>AGE</th>
</tr>
<tr th:each="emp : ${empList}">
<td th:text="${emp.id}">1</td>
<td th:text="${emp.name}">海</td>
<td th:text="${emp.age}">18</td>
</tr>
</table>
</body>
</html>
后台:
@GetMapping(value = "/hello") public String hello(Model model) { List<Emp> empList = new ArrayList<>(); empList.add(new Emp(1, "校長", 24)); empList.add(new Emp(2, "書記", 28)); empList.add(new Emp(3, "小海", 25)); model.addAttribute("empList", empList); return "hello"; } HelloController
更多循環深入,iterStat等示例,參考:http://blog.csdn.net/sun_jy2011/article/details/40710429
8.內置對象Utilites
一般不推薦在前端進行這些處理,前端頁面以減少邏輯為宜
#dates : utility methods for java.util.Date objects: formatting, component extraction, etc. #calendars : analogous to #dates , but for java.util.Calendar objects. #numbers : utility methods for formatting numeric objects. #strings : utility methods for String objects: contains, startsWith, prepending/appending, etc. #objects : utility methods for objects in general. #bools : utility methods for boolean evaluation. #arrays : utility methods for arrays. #lists : utility methods for lists. #sets : utility methods for sets. #maps : utility methods for maps. #aggregates : utility methods for creating aggregates on arrays or collections. #messages : utility methods for obtaining externalized messages inside variables expressions, in the same way as they would be obtained using #{...} syntax. #ids : utility methods for dealing with id attributes that might be repeated (for example, as a result of an iteration).
常用示例:
/* * 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()} #dates
/* * 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)} String
完整參考:點擊查看
四、常用標簽
// 類似於th:object和th:field等進行表單參數綁定還是很有用的!使用與注意事項,參見:這里
參考博文:https://www.cnblogs.com/hjwublog/p/5051732.html