一、Thymeleaf模版簡介
官方文檔:https://www.thymeleaf.org/doc/tutorials/3.0/usingthymeleaf.html#appendix-a-expression-basic-objects
中文文檔:
https://www.e-learn.cn/thymeleaf/thymeleaf-instroduce
SpringBoot提供了大量的模版引擎镀脂,包括FreeMarker缴阎、Groovy掏缎、Thymeleaf稠歉、Velcoity和Mustache箱蝠,SpringBoot中推薦使用Thymeleaf作為模版引擎,因為Thymeleaf提供了完美的SpringMVC支持。
Thymeleaf是一個java類庫宦搬,它是一個xml/xthml/html5的模版引擎牙瓢,可以作為MVC的Web應(yīng)用的View層。
- 通過xmlns:th=”http://www.thymeleaf.org”命名空間间校,將頁面轉(zhuǎn)換為動態(tài)試圖矾克,需要進行動態(tài)處理的元素使用“th:”作為前綴。
- 通過th:text=”${person.name}”訪問model中的屬性憔足。
- 通過th:each=”person:${people}”來做循環(huán)迭代胁附。
- 通過th:if=”${not #lists.isEmpty(people)}”來判斷people是否為空。
5 .通過th:src=”@{jquery-3.3.1.min.js}”來訪問Web中的靜態(tài)資源滓彰。 - 通過th:inline=”javascript”來添加script標(biāo)簽控妻,這樣在JavaScript代碼中即可訪問model中的屬性值。
- 通過“[[${}]]”格式來獲得實際值揭绑。
在傳統(tǒng)的SpringMVC中弓候,若我們需要集成一個模版引擎的話,需要定義ViewResolver他匪。而Thymeleaf提供了一個SpringTemplateEngine的類菇存,用來驅(qū)動SpringMVC下使用Thymeleaf模版引擎。而在SpringBoot中對Thymeleaf進行了自動配置邦蜜,可以在application中以spring.thymeleaf開發(fā)來進行配置依鸥,不配置的情況下模版的默認(rèn)目錄是templates。
在src/main/resource/static中放入需要引入的靜態(tài)資源:Bootstrap和jQuery悼沈。根據(jù)默認(rèn)的原則在src/main/resource/templates下創(chuàng)建index.html文件贱迟。
二、SpringBoot整合Thymeleaf
- Maven依賴
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
靜態(tài)資源
SpringBoot默認(rèn)的幾個靜態(tài)頁面的目錄:
/static井辆、/public关筒、/resources 、/META-INF/resources配置Thymeleaf杯缺,在application.properties下配置
#thymelea模板配置
spring.thymeleaf.cache=false
spring.thymeleaf.prefix=classpath:/templates/
spring.thymeleaf.suffix=.html
spring.thymeleaf.encoding=UTF-8
spring.thymeleaf.servlet.content-type=text/html
spring.thymeleaf.mode=HTML5
spring.thymeleaf.cache
是否開啟模板緩存蒸播,默認(rèn)true
spring.thymeleaf.check-template-location
是否檢查模板路徑是否存在,默認(rèn)true
spring.thymeleaf.content-type
指定Content-Type萍肆,默認(rèn)為: text/html
spring.thymeleaf.enabled
是否允許MVC使用Thymeleaf袍榆,默認(rèn)為: true
spring.thymeleaf.encoding
指定模板的編碼,默認(rèn)為: UTF-8
spring.thymeleaf.excluded-view-names
指定不使用模板的視圖名稱塘揣,多個以逗號分隔.
spring.thymeleaf.mode
**指定模板的模式包雀,具體查看StandardTemplateModeHandlers,默認(rèn)為: HTML5
spring.thymeleaf.mode = LEGACYHTML5
spring.thymeleaf.mode的默認(rèn)值是HTML5亲铡,其實是一個很嚴(yán)格的檢查才写,改為LEGACYHTML5可以得到一個可能更友好親切的格式要求葡兑。
**
spring.thymeleaf.prefix
指定模板的前綴,默認(rèn)為:classpath:/templates/
spring.thymeleaf.suffix
指定模板的后綴赞草,默認(rèn)為:.html
spring.thymeleaf.template-resolver-order
指定模板的解析順序讹堤,默認(rèn)為第一個.
spring.thymeleaf.view-names
指定使用模板的視圖名,多個以逗號分隔.
- 編寫Controller
@Controller
public class IndexController {
@GetMapping("/index")
public ModelAndView test(ModelAndView mv) {
//視圖文件名
mv.setViewName("index");
mv.addObject("name","歡迎使用Thymeleaf!");
return mv;
}
}
- 編寫html
在src/main/resources/templates目錄下創(chuàng)建:index.html
<!--引入命名空間-->
<html xmlns:th="http://www.thymeleaf.org">
<!DOCTYPE html>
<html>
<head lang="en">
<meta charset="UTF-8" />
<title>thymeleaf示例</title>
</head>
<body>
<h1>Hello thymeleaf</h1>
<h2 th:text="'名稱:'+${name}">默認(rèn)值</h2>
</body>
</html>
文本需要th:text屬性來設(shè)置厨疙。我們可以在文本元素中添加默認(rèn)值洲守,這樣當(dāng)Thymeleaf引擎處理失敗的時候頁面會顯示默認(rèn)值。${...}是變量表達(dá)式沾凄,將括號中的變量替換為其值梗醇。
三、基礎(chǔ)語法
th屬性:
常用th屬性解讀
html有的屬性撒蟀,Thymeleaf基本都有叙谨,而常用的屬性大概有七八個。其中th屬性執(zhí)行的優(yōu)先級從1~8牙肝,數(shù)字越低優(yōu)先級越高唉俗。
1)th:text :設(shè)置當(dāng)前元素的文本內(nèi)容,相同功能的還有th:utext配椭,兩者的區(qū)別在于前者不會轉(zhuǎn)義html標(biāo)簽虫溜,后者會。優(yōu)先級不高:order=7
2)th:value:設(shè)置當(dāng)前元素的value值股缸,類似修改指定屬性的還有th:src衡楞,th:href。優(yōu)先級不高:order=6
3)th:each:遍歷循環(huán)元素敦姻,和th:text或th:value一起使用瘾境。注意該屬性修飾的標(biāo)簽位置,詳細(xì)往后看镰惦。優(yōu)先級很高:order=2
4)th:if:條件判斷迷守,類似的還有th:unless,th:switch旺入,th:case兑凿。優(yōu)先級較高:order=3
5)th:insert:代碼塊引入,類似的還有th:replace茵瘾,th:include礼华,三者的區(qū)別較大,若使用不恰當(dāng)會破壞html結(jié)構(gòu)拗秘,常用于公共代碼塊提取的場景圣絮。優(yōu)先級最高:order=1
6)th:fragment:定義代碼塊,方便被th:insert引用雕旨。優(yōu)先級最低:order=8
7)th:object:聲明變量扮匠,一般和*{}一起配合使用捧请,達(dá)到偷懶的效果。優(yōu)先級一般:order=4
8)th:attr:修改任意屬性棒搜,實際開發(fā)中用的較少血久,因為有豐富的其他th屬性幫忙,類似的還有th:attrappend帮非,th:attrprepend。優(yōu)先級一般:order=5
- 變量表達(dá)式 {}" 獲取對象屬性 讹蘑。例如:
<form id="userForm">
<input id="id" name="id" th:value="${user.id}"/>
<input id="username" name="username" th:value="${user.username}"/>
<input id="password" name="password" th:value="${user.password}"/>
</form>
<div th:text="hello"></div>
<div th:text="${user.username}"></div>
- 選擇變量表達(dá)式 {}
使用方法:首先通過th:object 獲取對象末盔,然后使用th:xx = "{}"獲取對象屬性。
這種簡寫風(fēng)格極為清爽座慰,推薦大家在實際項目中使用陨舱。 例如:
<form id="userForm" th:object="${user}">
<input id="id" name="id" th:value="{id}"/>
<input id="username" name="username" th:value="{username}"/>
<input id="password" name="password" th:value="*{password}"/>
</form> - 鏈接表達(dá)式 @{}
使用方法:通過鏈接表達(dá)式@{}直接拿到應(yīng)用路徑,然后拼接靜態(tài)資源路徑版仔。例如:
<script th:src="@{/webjars/jquery/jquery.js}"></script>
<link th:href="@{/webjars/bootstrap/css/bootstrap.css}" rel="stylesheet" type="text/css">
- 片段表達(dá)式 ~{}
Thymeleaf 3.0 引入了一個新的片段表達(dá)式游盲。形如:~{commons::footer}。
該特性十分有用(比如解決定義通用的header和footer的問題)
base.html
片段表達(dá)式是Thymeleaf的特色之一蛮粮,細(xì)粒度可以達(dá)到標(biāo)簽級別益缎,這是JSP無法做到的。
片段表達(dá)式擁有三種語法:
~{ viewName } 表示引入完整頁面
~{ viewName ::selector} 表示在指定頁面尋找片段 其中selector可為片段名然想、jquery選擇器等
~{ ::selector} 表示在當(dāng)前頁尋找
使用方法:首先通過th:fragment定制片段 莺奔,然后通過th:replace 填寫片段路徑和片段名。例如:
<!-- /views/common/head.html-->
<head th:fragment="static">
<script th:src="@{/webjars/jquery/3.3.1/jquery.js}"></script>
</head>
<!-- /views/your.html -->
<div th:replace="~{common/head::static}"></div>
在實際使用中变泄,我們往往使用更簡潔的表達(dá)令哟,去掉表達(dá)式外殼直接填寫片段名。例如:
<!-- your.html -->
<div th:replace="common/head::static"></div>
值得注意的是妨蛹,使用替換路徑th:replace 開頭請勿添加斜杠屏富,避免部署運行的時候出現(xiàn)路徑報錯。(因為默認(rèn)拼接的路徑為spring.thymeleaf.prefix = classpath:/templates/)
支持兩種語法結(jié)構(gòu)
推薦:~{templatename::fragmentname}
支持:~{templatename::#id}
templatename:模版名蛙卤,Thymeleaf會根據(jù)模版名解析完整路徑:/resources/templates/templatename.html狠半,要注意文件的路徑。
fragmentname:片段名表窘,Thymeleaf通過th:fragment聲明定義代碼塊典予,即:th:fragment="fragmentname"
id:HTML的id選擇器,使用時要在前面加上#號乐严,不支持class選擇器瘤袖。
代碼塊表達(dá)式的使用
代碼塊表達(dá)式需要配合th屬性(th:insert,th:replace昂验,th:include)一起使用捂敌。
th:insert:將代碼塊片段整個插入到使用了th:insert的HTML標(biāo)簽中艾扮,
th:replace:將代碼塊片段整個替換使用了th:replace的HTML標(biāo)簽中,
th:include:將代碼塊片段包含的內(nèi)容插入到使用了th:include的HTML標(biāo)簽中占婉,
用一個官方例子來區(qū)分三者的不同泡嘴,第三部分會通過實戰(zhàn)再次用到該知識。
<!--th:fragment定義代碼塊標(biāo)識-->
<footer th:fragment="copy">
© 2011 The Good Thymes Virtual Grocery
</footer>
<!--三種不同的引入方式-->
<div th:insert="footer :: copy"></div>
<div th:replace="footer :: copy"></div>
<div th:include="footer :: copy"></div>
<!--th:insert是在div中插入代碼塊逆济,即多了一層div-->
<div>
<footer>
© 2011 The Good Thymes Virtual Grocery
</footer>
</div>
<!--th:replace是將代碼塊代替當(dāng)前div岖赋,其html結(jié)構(gòu)和之前一致-->
<footer>
© 2011 The Good Thymes Virtual Grocery
</footer>
<!--th:include是將代碼塊footer的內(nèi)容插入到div中荣茫,即少了一層footer-->
<div>
© 2011 The Good Thymes Virtual Grocery
</div>
- 消息表達(dá)式
即通常的國際化屬性:#{msg} 用于獲取國際化語言翻譯值。例如:
<title th:text="#{user.title}"></title>
- 其它表達(dá)式
在基礎(chǔ)語法中,默認(rèn)支持字符串連接钝的、數(shù)學(xué)運算涛舍、布爾邏輯和三目運算等王凑。例如:
<input name="name" th:value="${'I am '+(user.name!=null?user.name:'NoBody')}"/>
- 注釋
Thymeleaf 注釋:
1获雕、<!--/* This code will be removed at Thymeleaf parsing time! */-->
2、<!--/*-->
<div>
you can see me only before Thymeleaf processes me!
</div>
<!--*/-->
3岛马、<!--/*/
<div th:text="${...}">
...
</div>
/*/-->
四棉姐、迭代循環(huán)
想要遍歷List集合很簡單,配合th:each 即可快速完成迭代啦逆。例如遍歷用戶列表:
<div th:each="user:${userList}">
賬號:<input th:value="${user.username}"/>
密碼:<input th:value="${user.password}"/>
</div>
在集合的迭代過程還可以獲取狀態(tài)變量伞矩,只需在變量后面指定狀態(tài)變量名即可,狀態(tài)變量可用于獲取集合的下標(biāo)/序號蹦浦、總數(shù)扭吁、是否為單數(shù)/偶數(shù)行、是否為第一個/最后一個盲镶。例如:
<div th:each="user,stat:${userList}" th:class="${stat.even}?'even':'odd'">
下標(biāo):<input th:value="${stat.index}"/>
序號:<input th:value="${stat.count}"/>
賬號:<input th:value="${user.username}"/>
密碼:<input th:value="${user.password}"/>
</div>
如果缺省狀態(tài)變量名侥袜,則迭代器會默認(rèn)幫我們生成以變量名開頭的狀態(tài)變量 xxStat, 例如:
<div th:each="user:${userList}" th:class="${userStat.even}?'even':'odd'">
下標(biāo):<input th:value="${userStat.index}"/>
序號:<input th:value="${userStat.count}"/>
賬號:<input th:value="${user.username}"/>
密碼:<input th:value="${user.password}"/>
</div>
th:remove
th:remove的值如下:
1.all:刪除包含標(biāo)簽和所有的孩子溉贿。
2.body:不包含標(biāo)記刪除,但刪除其所有的孩子枫吧。
3.tag:包含標(biāo)記的刪除,但不刪除它的孩子。
4.all-but-first:刪除所有包含標(biāo)簽的孩子,除了第一個宇色。
5.none:什么也不做九杂。這個值是有用的動態(tài)評估。
五宣蠕、條件判斷
條件判斷通常用于動態(tài)頁面的初始化例隆,例如:
<div th:if="${userList}">
<div>的確存在..</div>
</div>
如果想取反則使用unless 例如:
<div th:unless="${userList}">
<div>不存在..</div>
</div>
六、日期格式化
使用默認(rèn)的日期格式(toString方法) 并不是我們預(yù)期的格式:Mon Dec 03 23:16:50 CST 2018
<input type="text" th:value="${user.createTime}"/>
此時可以通過時間工具類#dates來對日期進行格式化:2018-12-03 23:16:50
<input type="text" th:value="${#dates.format(user.createTime,'yyyy-MM-dd HH:mm:ss')}"/>
七抢蚀、內(nèi)聯(lián)寫法
(1)為什么要使用內(nèi)聯(lián)寫法镀层?·答:因為 JS無法獲取服務(wù)端返回的變量。
(2)如何使用內(nèi)聯(lián)表達(dá)式皿曲?答:標(biāo)準(zhǔn)格式為:[[${xx}]] 唱逢,可以讀取服務(wù)端變量吴侦,也可以調(diào)用內(nèi)置對象的方法。例如獲取用戶變量和應(yīng)用路徑:
<script th:inline="javascript">
var user = [[${user}]];`
var APP_PATH = [[${#request.getContextPath()}]];
var LANG_COUNTRY = [[${#locale.getLanguage()+'_'+#locale.getCountry()}]];
</script>
(3)標(biāo)簽引入的JS里面能使用內(nèi)聯(lián)表達(dá)式嗎坞古?答:不能备韧!內(nèi)聯(lián)表達(dá)式僅在頁面生效,因為Thymeleaf只負(fù)責(zé)解析一級視圖痪枫,不能識別外部標(biāo)簽JS里面的表達(dá)式织堂。
八、七大基礎(chǔ)對象:
${#ctx} 上下文對象奶陈,可用于獲取其它內(nèi)置對象捧挺。
${#vars}: 上下文變量。
${#locale}:上下文區(qū)域設(shè)置尿瞭。
${#request}: HttpServletRequest對象。
${#response}: HttpServletResponse對象翅睛。
${#session}: HttpSession對象声搁。
${#servletContext}: ServletContext對象。
常用的工具類:
#strings:字符串工具類
#lists:List 工具類
#arrays:數(shù)組工具類
#sets:Set 工具類
#maps:常用Map方法捕发。
#objects:一般對象類疏旨,通常用來判斷非空
#bools:常用的布爾方法。
#execInfo:獲取頁面模板的處理信息扎酷。
#messages:在變量表達(dá)式中獲取外部消息的方法檐涝,與使用#{...}語法獲取的方法相同。
#uris:轉(zhuǎn)義部分URL / URI的方法法挨。
#conversions:用于執(zhí)行已配置的轉(zhuǎn)換服務(wù)的方法谁榜。
#dates:時間操作和時間格式化等。
#calendars:用于更復(fù)雜時間的格式化凡纳。
#numbers:格式化數(shù)字對象的方法窃植。
#aggregates:在數(shù)組或集合上創(chuàng)建聚合的方法。
#ids:處理可能重復(fù)的id屬性的方法荐糜。
九巷怜、常見問題
-
去掉IDE thymeleaf Html顯示紅色波浪線
打開IDE的file->setting->左上角搜索inspections,然后在右邊的搜索欄輸入thy,就會顯示如下頁面暴氏,將Expression variables validation的√去掉延塑,然后點擊確定。
- 日期格式處理
添加:
@Column
@DateTimeFormat(pattern="yyyy-MM-dd")
private Date createtime;
顯示:
//java代碼:
@GetMapping("/index")
public String test(Model model) {
model.addAttribute("date",new Date());
//視圖文件名
return "index";
}
//H5界面
<span th:text="${#dates.format(date, 'yyyy-MM-dd')}">2018-05-06</span>
或者
<span th:text="${#dates.format(date,'yyyy-MM-dd HH:mm:ss')}">2019-05-06 00:00:00</span>