SpringBoot--實戰開發--整合Thymeleaf模版(十)

一、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應用的View層。

  1. 通過xmlns:th=”http://www.thymeleaf.org”命名空間,將頁面轉換為動態試圖,需要進行動態處理的元素使用“th:”作為前綴。
  2. 通過th:text=”${person.name}”訪問model中的屬性。
  3. 通過th:each=”person:${people}”來做循環迭代。
  4. 通過th:if=”${not #lists.isEmpty(people)}”來判斷people是否為空。
    5 .通過th:src=”@{jquery-3.3.1.min.js}”來訪問Web中的靜態資源。
  5. 通過th:inline=”javascript”來添加script標簽,這樣在JavaScript代碼中即可訪問model中的屬性值。
  6. 通過“[[${}]]”格式來獲得實際值。
    在傳統的SpringMVC中,若我們需要集成一個模版引擎的話,需要定義ViewResolver。而Thymeleaf提供了一個SpringTemplateEngine的類,用來驅動SpringMVC下使用Thymeleaf模版引擎。而在SpringBoot中對Thymeleaf進行了自動配置,可以在application中以spring.thymeleaf開發來進行配置,不配置的情況下模版的默認目錄是templates。
    在src/main/resource/static中放入需要引入的靜態資源:Bootstrap和jQuery。根據默認的原則在src/main/resource/templates下創建index.html文件。

二、SpringBoot整合Thymeleaf

  1. Maven依賴
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
  1. 靜態資源
    SpringBoot默認的幾個靜態頁面的目錄:
    /static、/public、/resources 、/META-INF/resources

  2. 配置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
是否開啟模板緩存,默認true
spring.thymeleaf.check-template-location
是否檢查模板路徑是否存在,默認true
spring.thymeleaf.content-type
指定Content-Type,默認為: text/html
spring.thymeleaf.enabled
是否允許MVC使用Thymeleaf,默認為: true
spring.thymeleaf.encoding
指定模板的編碼,默認為: UTF-8
spring.thymeleaf.excluded-view-names
指定不使用模板的視圖名稱,多個以逗號分隔.
spring.thymeleaf.mode
**指定模板的模式,具體查看StandardTemplateModeHandlers,默認為: HTML5
spring.thymeleaf.mode = LEGACYHTML5
spring.thymeleaf.mode的默認值是HTML5,其實是一個很嚴格的檢查,改為LEGACYHTML5可以得到一個可能更友好親切的格式要求。
**
spring.thymeleaf.prefix
指定模板的前綴,默認為:classpath:/templates/
spring.thymeleaf.suffix
指定模板的后綴,默認為:.html
spring.thymeleaf.template-resolver-order
指定模板的解析順序,默認為第一個.
spring.thymeleaf.view-names
指定使用模板的視圖名,多個以逗號分隔.

  1. 編寫Controller
@Controller
public class IndexController {
    @GetMapping("/index")
    public ModelAndView test(ModelAndView mv) {
        //視圖文件名
        mv.setViewName("index");
        mv.addObject("name","歡迎使用Thymeleaf!");
        return mv;
    }
}
  1. 編寫html
    在src/main/resources/templates目錄下創建: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}">默認值</h2>
</body>
</html>

文本需要th:text屬性來設置。我們可以在文本元素中添加默認值,這樣當Thymeleaf引擎處理失敗的時候頁面會顯示默認值。${...}是變量表達式,將括號中的變量替換為其值。

三、基礎語法

th屬性:
常用th屬性解讀
html有的屬性,Thymeleaf基本都有,而常用的屬性大概有七八個。其中th屬性執行的優先級從1~8,數字越低優先級越高。
1)th:text :設置當前元素的文本內容,相同功能的還有th:utext,兩者的區別在于前者不會轉義html標簽,后者會。優先級不高:order=7
2)th:value:設置當前元素的value值,類似修改指定屬性的還有th:src,th:href。優先級不高:order=6
3)th:each:遍歷循環元素,和th:text或th:value一起使用。注意該屬性修飾的標簽位置,詳細往后看。優先級很高:order=2
4)th:if:條件判斷,類似的還有th:unless,th:switch,th:case。優先級較高:order=3
5)th:insert:代碼塊引入,類似的還有th:replace,th:include,三者的區別較大,若使用不恰當會破壞html結構,常用于公共代碼塊提取的場景。優先級最高:order=1
6)th:fragment:定義代碼塊,方便被th:insert引用。優先級最低:order=8
7)th:object:聲明變量,一般和*{}一起配合使用,達到偷懶的效果。優先級一般:order=4
8)th:attr:修改任意屬性,實際開發中用的較少,因為有豐富的其他th屬性幫忙,類似的還有th:attrappend,th:attrprepend。優先級一般:order=5

  1. 變量表達式 {} 使用方法:直接使用th:xx = "{}" 獲取對象屬性 。例如:
<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>
  1. 選擇變量表達式 {}
    使用方法:首先通過th:object 獲取對象,然后使用th:xx = "
    {}"獲取對象屬性。
    這種簡寫風格極為清爽,推薦大家在實際項目中使用。 例如:
    <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>
  2. 鏈接表達式 @{}
    使用方法:通過鏈接表達式@{}直接拿到應用路徑,然后拼接靜態資源路徑。例如:
<script th:src="@{/webjars/jquery/jquery.js}"></script>
<link th:href="@{/webjars/bootstrap/css/bootstrap.css}" rel="stylesheet" type="text/css">
  1. 片段表達式 ~{}
    Thymeleaf 3.0 引入了一個新的片段表達式。形如:~{commons::footer}。
    該特性十分有用(比如解決定義通用的header和footer的問題)
    base.html

片段表達式是Thymeleaf的特色之一,細粒度可以達到標簽級別,這是JSP無法做到的。
片段表達式擁有三種語法:
~{ viewName } 表示引入完整頁面
~{ viewName ::selector} 表示在指定頁面尋找片段 其中selector可為片段名、jquery選擇器等
~{ ::selector} 表示在當前頁尋找
使用方法:首先通過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>

在實際使用中,我們往往使用更簡潔的表達,去掉表達式外殼直接填寫片段名。例如:

<!-- your.html -->
<div th:replace="common/head::static"></div>

值得注意的是,使用替換路徑th:replace 開頭請勿添加斜杠,避免部署運行的時候出現路徑報錯。(因為默認拼接的路徑為spring.thymeleaf.prefix = classpath:/templates/)
支持兩種語法結構
推薦:~{templatename::fragmentname}
支持:~{templatename::#id}
templatename:模版名,Thymeleaf會根據模版名解析完整路徑:/resources/templates/templatename.html,要注意文件的路徑。
fragmentname:片段名,Thymeleaf通過th:fragment聲明定義代碼塊,即:th:fragment="fragmentname"
id:HTML的id選擇器,使用時要在前面加上#號,不支持class選擇器。
代碼塊表達式的使用
代碼塊表達式需要配合th屬性(th:insert,th:replace,th:include)一起使用。
th:insert:將代碼塊片段整個插入到使用了th:insert的HTML標簽中,
th:replace:將代碼塊片段整個替換使用了th:replace的HTML標簽中,
th:include:將代碼塊片段包含的內容插入到使用了th:include的HTML標簽中,
用一個官方例子來區分三者的不同,第三部分會通過實戰再次用到該知識。

<!--th:fragment定義代碼塊標識-->
<footer th:fragment="copy">
&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>
    &copy; 2011 The Good Thymes Virtual Grocery
    </footer>
</div>
<!--th:replace是將代碼塊代替當前div,其html結構和之前一致-->
<footer>
&copy; 2011 The Good Thymes Virtual Grocery
</footer>
<!--th:include是將代碼塊footer的內容插入到div中,即少了一層footer-->
<div>
&copy; 2011 The Good Thymes Virtual Grocery
</div>
  1. 消息表達式
    即通常的國際化屬性:#{msg} 用于獲取國際化語言翻譯值。例如:
 <title th:text="#{user.title}"></title>
  1. 其它表達式
    在基礎語法中,默認支持字符串連接、數學運算、布爾邏輯和三目運算等。例如:
<input name="name" th:value="${'I am '+(user.name!=null?user.name:'NoBody')}"/>
  1. 注釋
    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>
/*/-->

四、迭代循環

想要遍歷List集合很簡單,配合th:each 即可快速完成迭代。例如遍歷用戶列表:

<div th:each="user:${userList}">
    賬號:<input th:value="${user.username}"/>
    密碼:<input th:value="${user.password}"/>
</div>

在集合的迭代過程還可以獲取狀態變量,只需在變量后面指定狀態變量名即可,狀態變量可用于獲取集合的下標/序號、總數、是否為單數/偶數行、是否為第一個/最后一個。例如:

<div th:each="user,stat:${userList}" th:class="${stat.even}?'even':'odd'">
    下標:<input th:value="${stat.index}"/>
    序號:<input th:value="${stat.count}"/>
    賬號:<input th:value="${user.username}"/>
    密碼:<input th:value="${user.password}"/>
</div>

如果缺省狀態變量名,則迭代器會默認幫我們生成以變量名開頭的狀態變量 xxStat, 例如:

<div th:each="user:${userList}" th:class="${userStat.even}?'even':'odd'">
    下標:<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:刪除包含標簽和所有的孩子。
  2.body:不包含標記刪除,但刪除其所有的孩子。
  3.tag:包含標記的刪除,但不刪除它的孩子。
  4.all-but-first:刪除所有包含標簽的孩子,除了第一個。
  5.none:什么也不做。這個值是有用的動態評估。

五、條件判斷

條件判斷通常用于動態頁面的初始化,例如:

<div th:if="${userList}">
    <div>的確存在..</div>
</div>

如果想取反則使用unless 例如:

<div th:unless="${userList}">
    <div>不存在..</div>
</div>

六、日期格式化

使用默認的日期格式(toString方法) 并不是我們預期的格式: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')}"/>

七、內聯寫法

(1)為什么要使用內聯寫法?·答:因為 JS無法獲取服務端返回的變量。
(2)如何使用內聯表達式?答:標準格式為:[[${xx}]] ,可以讀取服務端變量,也可以調用內置對象的方法。例如獲取用戶變量和應用路徑:

    <script th:inline="javascript">
        var user = [[${user}]];`
        var APP_PATH = [[${#request.getContextPath()}]];
        var LANG_COUNTRY = [[${#locale.getLanguage()+'_'+#locale.getCountry()}]];
    </script>

(3)標簽引入的JS里面能使用內聯表達式嗎?答:不能!內聯表達式僅在頁面生效,因為Thymeleaf只負責解析一級視圖,不能識別外部標簽JS里面的表達式。

八、七大基礎對象:

${#ctx} 上下文對象,可用于獲取其它內置對象。
${#vars}:    上下文變量。
${#locale}:上下文區域設置。
${#request}: HttpServletRequest對象。
${#response}: HttpServletResponse對象。
${#session}: HttpSession對象。
${#servletContext}:  ServletContext對象。
常用的工具類:
#strings:字符串工具類
#lists:List 工具類
#arrays:數組工具類
#sets:Set 工具類
#maps:常用Map方法。
#objects:一般對象類,通常用來判斷非空
#bools:常用的布爾方法。
#execInfo:獲取頁面模板的處理信息。
#messages:在變量表達式中獲取外部消息的方法,與使用#{...}語法獲取的方法相同。
#uris:轉義部分URL / URI的方法。
#conversions:用于執行已配置的轉換服務的方法。
#dates:時間操作和時間格式化等。
#calendars:用于更復雜時間的格式化。
#numbers:格式化數字對象的方法。
#aggregates:在數組或集合上創建聚合的方法。
#ids:處理可能重復的id屬性的方法。

九、常見問題

  1. 去掉IDE thymeleaf Html顯示紅色波浪線
    打開IDE的file->setting->左上角搜索inspections,然后在右邊的搜索欄輸入thy,就會顯示如下頁面,將Expression variables validation的√去掉,然后點擊確定。


    紅色波浪線
  2. 日期格式處理
    添加:
    @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>
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 227,702評論 6 531
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,143評論 3 415
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 175,553評論 0 373
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,620評論 1 307
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,416評論 6 405
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 54,940評論 1 321
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,024評論 3 440
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,170評論 0 287
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 48,709評論 1 333
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,597評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 42,784評論 1 369
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,291評論 5 357
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,029評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,407評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,663評論 1 280
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,403評論 3 390
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 47,746評論 2 370

推薦閱讀更多精彩內容