Thymeleaf
Thymeleaf是最近SpringBoot推薦支持的模板框架,官網在thymeleaf.org這裡。
我們為什麼要用Thymeleaf來作為模板引擎呢?官網給了我們一個非常令人信服的解釋:
Thymeleaf is a modern server-side Java template engine for both web and standalone environments.>
基本寫法就像下面這樣:
<table> <thead> <tr> <th th:text="#{msgs.headers.name}">Name</th> <th th:text="#{msgs.headers.price}">Price</th> </tr> </thead> <tbody> <tr th:each="prod: ${allProducts}"> <td th:text="${prod.name}">Oranges</td> <td th:text="${#numbers.formatDecimal(prod.price, 1, 2)}">0.99</td> </tr> </tbody> </table>
沒錯,由於這個模板是以xml的格式以屬性的形式嵌入在html裡,因此不僅適合後台人員使用,也能直接在沒有後台程序的情況下直接由浏覽器渲染,因為浏覽器會自動忽視html未定義的屬性。
這個屬性還是非常吸引人的,畢竟我們做後台最麻煩的就是在亂七八糟的前台模板加代碼,加完代碼之後前台的也不知道加的代碼對不對,非得先跑一遍才能知道。如果模板文件能夠直接由前端人員編寫那該多好,而且前端人員在編寫的時候就能知道這個代碼能不能跑,豈不是非常開心?
參考文檔
Thymeleaf的文檔鏈接在這裡,細節可以直接去搜索,下面主要列舉下我經常遇到的一些問題。
模板定義
由於我們很多的IDE都會提供很好的提示工作,因此我們有必要告訴IDE我們使用的模板規范以方便他給我們提供服務。Thymeleaf的一般規范是這樣的:
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:th="http://www.thymeleaf.org"> ... </html>
把我們需要編寫的DOM放在這個html標簽裡面就好了。
這句話做了什麼事呢?其實就是定義了一個叫th的名空間,所有Thymeleaf的屬性都是在這個名空間下面。
靜態文件的加載
我們知道一個網頁中加載的靜態文件通常有一個十分尴尬的問題,比如對於bootstrap.css,就是如果我們能讓IDE識別這個文件,那麼我們得用相對路徑來引入這個文件。這樣我們的IDE才能加載到這個文件,並且給予我們相應的提示。但是如果我們想要在發布後服務器能夠加載這個文件,我們就必須用相對於resources或者static的位置來引入靜態文件。顯然,一般情況下我們不能兼顧這兩個問題,只能要麼在編寫的時候用相對自己的路徑,然後在發布的時候用相對於項目資源文件夾的路徑,要麼就只能放棄IDE的提示,非常尴尬。
而在Thymeleaf中,我們可很好的處理這一點。在引入資源的時候,我們可以寫類似下面的代碼:
<link rel="stylesheet" type="text/css" media="all" href="../../css/gtvg.css" rel="external nofollow" th:href="@{/css/gtvg.css}" rel="external nofollow" />
當我們在沒有後台渲染的情況下,浏覽器會認得href,但是不認得th:href,這樣它就會選擇以相對與本文件的相對路徑去加載靜態文件。而且我們的IDE也能識別這樣的加載方式,從而給我們提示。
當我們在有後台渲染的情況下,後台會把這個標簽渲染為這樣:
<link rel="stylesheet" type="text/css" media="all" href="/css/gtvg.css" rel="external nofollow" />
原來的href標簽會被替換成相對於項目的路徑,因此服務器就能找到正確的資源,從而正確渲染。
非常的智能而且方便。
這裡需要注意到所有的路徑我們是用”@{}”來引用,而不是”${}”,因為後者是用來引用變量名的,而前者是引用路徑的,因此我們在這裡用的是前者。可是如果我們是把路徑寫在變量裡,那麼就要用後者來引用了。
常量的渲染以及文字國際化
很多情況下我們並不希望在代碼裡硬編碼進文字,我們希望把文字提取成統一的代號,這樣方便管理,也方便更改語言。
我們要做的首先是創建一個語言文件,比如message_chinese.properties:
title=這是標題 message1=這是消息2 message2=這是消息2 ....
然後我們在application.properties
裡加上下面這行注冊這個語言文件:
spring.messages.basename=message_chinese
這樣,我們在模板裡就可以通過#{消息名}來獲取這個消息對應的真正的文字:
<title th:text="#{title}"></title>
變量的渲染
對於一個模板文件來說,最重要的事情莫過與傳遞變量了。
這件事情非常簡單,主要分為兩步,首先是在SpringBoot的Controller裡給Model傳進參數:
@Controller public class IndexController { @RequestMapping(path = {"index", "/"}, method = {RequestMethod.GET}) public String index(Model model) { model.addAttribute("var1", "value1"); model.addAttribute("src1", "https://www.baidu.com"); Map<String,Object> map=new HashMap<>(); map.put("src1","/a.png"); map.put("src2","/b.png"); model.addAttribute("src", map); return "index"; } }
這樣我們就可以在模板裡通過th:屬性名="${變量名}"這種方式來傳值,比如:
<span th:text="${var1}"></span> <a th:href="${src1}" rel="external nofollow" >baidu</a> <img th:src="${src.src1}" />
定義十分清楚,也很容易類比,支持層次選擇,不再細說。
循環語句
當我們需要動態加載一些帖子的時候,我們經常需要用循環語句,Thymeleaf中循環語句也很簡單,主要是依靠th:each這玩意來實現。
首先我們當然是在Controller裡創建可供循環的List對象並傳遞給model:
@Controller public class IndexController { @RequestMapping(path = {"index", "/"}, method = {RequestMethod.GET}) public String index(Model model) { List<String> list=new ArrayList<>(); for(int i=0;i<10;i++){ list.add(String.valueOf(i)); } model.addAttribute("list", list); return "index"; } }
然後在需要循環的地方這樣使用:
<div th:each="value:${list}" th:text="${value}"></div>
就能循環渲染這個list裡的元素了。
激活語句
所謂的激活語句(自己起得名字),就是在某些情況下我們想根據變量的值來選擇到底顯示還是不顯示這個標簽。用法也很見簡單,主要靠th:if跟th:unless:
<div th:if="${judge}" >if clause</div> <div th:unless="${judge}" >unless clause</div>
通過判斷judge這個變量是否不為空來控制這個標簽是否顯示。。。if跟unless互為反義詞。。。不解釋了。。。
選擇語句
類似於switch-case語句,非常簡單,見下例:
<div th:switch="${user.role}"> <p th:case="'admin'">User is an administrator</p> <p th:case="#{roles.manager}">User is a manager</p> </div>
這段代碼順便體現了一個小細節,如果想在th名空間裡直接填入字符串,我們必須再用一對引號來引用。。。
代碼分割引用
thymeleaf也提供了類似import的東西,可以將很多代碼塊抽象成模塊,然後在需要的時候引用,非常方便。具體的說,引用方式有兩種–replace和include。
比如有兩個文件
<!--footer.html--> <div th:fragment="copy">footer</div> <!--index.html--> <div th:include="footer :: copy">index</div>
通過這樣,我們就可以在index裡面引用footer裡面的這個div,我們用的是include,因此渲染的結果就是這樣:
<div> <div th:fragment="copy">footer</div> </div>
如果是replace,那就是整個標簽的替換,很好理解。
當然,除了用fragment來標識引用的部分,我們還可以用id來引用,具體可以參考文檔。
有時候我們可能希望在引用的時候傳遞參數,我們可以在引用時加上這樣的參數:
<!--index.html--> <div th:include="footer :: copy" th:with="param=${value}" >index</div>
這樣我們就可以把index頁面的value變量傳遞到footer頁面裡。非常簡單。
引用js的坑
有時候我們想用js變量來保存模板傳遞的參數,我們可以這樣來引用:
<script th:inline="javascript"> /*<![CDATA[*/ ... var username = /*[[${session.user.name}]]*/ 'Sebastian'; ... /*]]>*/ </script>
注意,這是官方推薦的寫法,注意以下幾點。
我們要用inline來指定這個script標簽;
我們需要注釋<![CDATA[,]]>對,否則就會無法在js中使用比較符號;
我們要用[[${value}]]來引用模板變量;
我們要在變量外面也套上注釋\**\,並在後面添加上默認的值,這是為了前端開發人員能在沒有後台的情況下正常渲染。
最後
當前我遇到的基本上靠上面的知識都足以解決了,更多高級用法可以直接讀文檔,到時候用到再來添加0.0。
以上所述是小編給大家介紹的SpringBoot中的Thymeleaf用法,希望對大家有所幫助,如果大家有任何疑問請給我留言,小編會及時回復大家的。在此也非常感謝大家對網站的支持!