SpringBoot?整合Thymeleaf教程及使用方法
Thymeleaf 是一款用于渲染 XML/XHTML/HTML5 內容的模板引擎。它與 JSP,Velocity,FreeMaker 等模板引擎類似,也可以輕易地與 Spring MVC 等 Web 框架集成。與其它模板引擎相比,Thymeleaf 最大的特點是,即使不啟動 Web 應用,也可以直接在瀏覽器中打開并正確顯示模板頁面 。
一、整合Thymeleaf
1、引入Thymeleaf starter依賴
<!-- thymeleaf 相關依賴 --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-thymeleaf</artifactId> </dependency>
2、在 application.properties 添加 Thymeleaf 相關配置
server.port= 8092 #關閉 Thymeleaf 的緩存開發(fā)過程中無需重啟 spring.thymeleaf.cache = false #設置thymeleaf頁面的編碼 spring.thymeleaf.encoding=UTF-8 spring.thymeleaf.mode=HTML5 #設置thymeleaf頁面的后綴 spring.thymeleaf.suffix=.html #設置thymeleaf頁面的存儲路徑 spring.thymeleaf.prefix=classpath:/templates/
Thymeleaf默認會開啟頁面緩存,提高頁面并發(fā)能力。但會導致我們修改頁面不會立即被展現,因此我們關閉緩存:spring.thymeleaf.cache=false
修改完畢頁面,需要使用快捷鍵:Ctrl + Shift + F9來刷新工程。
3、編寫訪問 Thymeleaf 頁面 Controller
@Controller @RequestMapping("/hello") public class ThymeleafHelloWrodController { @RequestMapping({"/", "/index"}) @ResponseBody public String index(Model model,String id) { model.addAttribute("msg", "welcome you!" + id); Map<String,String> user = new HashMap<>(); user.put("uid","11111"); user.put("umc","testmc"); user.put("etel","13550125501"); model.addAttribute("user", user); return "index"; //返回的是index.html的頁面 } @RequestMapping("/thymeleaf") public String helloThymeleaf(Model model){ model.addAttribute("hello","hello Thymeleaf!"); return "hello/index"; } }
后臺springmvc 使用 Model 傳入數據 (包名:org.springframework.ui.Model)
Thymeleaf的主要作用是把model中的數據渲染到html中,因此其語法主要是如何解析model中的數據。
3、Controller類編寫(@RequestBody注解是必須加上的,將java對象轉為json格式的數據。如果出現頁面顯示不了又沒有報錯可能就是Controller類沒有加@RequestBody)
返回的是Thymeleaf 模板對應的index.html的頁面
- public interface Model{} //是一個接口 - public class ModelMap extends LinkedhashMap<String,Object>{} //繼承了LinkedHashMap - public class ExtendedModelMap extends MOdelMap implements Model{} //繼承了ModelMap又實現了Model接口 - public class BindingAwareModelMap{} //這個類對應的子類,就可以去實例化ModelMap也可以實例化Model - //因為ModelMap繼承了LinkedHashMap所以說,BindingAwareModelMap也可以實例化Map集合
4、Thymeleaf 頁面代碼如下
src/main/resources/templates/index.html
<!DOCTYPE html> <html xmlns="http://www.w3.org/1999/xhtml" xmlns:th="http://www.thymeleaf.org"> <head> <meta charset="utf-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="renderer" content="webkit"> <title>首頁</title> <link rel="shortcut icon" th:href="@{/favicon.ico}" rel="external nofollow" /> <link th:href="@{/static/css/bootstrap.min.css}" rel="external nofollow" rel="stylesheet"/> <link th:href="@{/static/css/font-awesome.min.css}" rel="external nofollow" rel="stylesheet"/> </head> <body class="fixed-sidebar full-height-layout gray-bg" style="overflow:hidden"> <div id="wrapper"> <h1 th:text="${msg}"></h1> <p data-th-text="${msg}">test p</p> <p th:inline="text">p:[(${msg})]</p> </div> <h2> <p>Name: <span th:text="${user.uid}">Jack</span>.</p> <p>Age: <span th:text="${user.umc}">21</span>.</p> <p>friend: <span th:text="${user.etel}">Rose</span>.</p> </h2> <script th:src="@{/static/js/jquery.min.js}"></script> <script th:src="@{/static/js/bootstrap.min.js}"></script> <script> </script> </body> </html>
5、訪問頁面
http://localhost:8092/index
http://localhost:8092/index?id=test
二、Thymeleaf 使用教程
Thymeleaf 模板引擎具有以下特點:
動靜結合:Thymeleaf 既可以直接使用瀏覽器打開,查看頁面的靜態(tài)效果,也可以通過 Web 應用程序進行訪問,查看動態(tài)頁面效果。
開箱即用:Thymeleaf 提供了 Spring 標準方言以及一個與 SpringMVC 完美集成的可選模塊,可以快速的實現表單綁定、屬性編輯器、國際化等功能。
多方言支持:它提供了 Thymeleaf 標準和 Spring 標準兩種方言,可以直接套用模板實現 JSTL、 OGNL 表達式;必要時,開發(fā)人員也可以擴展和創(chuàng)建自定義的方言。
與 SpringBoot 完美整合:SpringBoot 為 Thymeleaf 提供了的默認配置,并且還為 Thymeleaf 設置了視圖解析器,因此 Thymeleaf 可以與 Spring Boot 完美整合。
1、在頁面的 html 標簽中聲明名稱空間
<html xmlns:th="http://www.thymeleaf.org">
在 html 標簽中聲明此名稱空間,可避免編輯器出現 html 驗證錯誤,但這一步并非必須進行的,即使我們不聲明該命名空間,也不影響 Thymeleaf 的使用。
把html 的名稱空間,改成:xmlns:th="http://www.thymeleaf.org" 會有語法提示
2、標準表達式語法
Thymeleaf的主要作用是把model中的數據渲染到html中,因此其語法主要是如何解析model中的數據。通過${}來獲取model中的變量,注意這不是el表達式,而是ognl表達式,但是語法非常像。
Thymeleaf崇尚自然模板,意思就是模板是純正的html代碼,脫離模板引擎,在純靜態(tài)環(huán)境也可以直接運行。現在如果我們直接在html中編寫 ${}這樣的表達式,顯然在靜態(tài)環(huán)境下就會出錯,這不符合Thymeleaf的理念。
<h1> 歡迎您:<span th:text="${user.name}">請登錄</span> </h1>
靜態(tài)情況下,th指令不會被識別,而是顯示默認值:請登錄
但是瀏覽器也不會報錯,把它當做一個普通屬性處理。這樣span的默認值請登錄就會展現在頁面
如果是在Thymeleaf環(huán)境下,th指令就會被識別和解析,而th:text的含義就是替換所在標簽中的文本內容,于是user.name的值就替代了 span中默認的請登錄如果不支持這種th:的命名空間寫法,那么可以把th:text換成 data-th-text,Thymeleaf也可以兼容。
th:text指令出于安全考慮,會把表達式讀取到的值進行處理,防止html的注入。
例如,<p>你好</p>將會被格式化輸出為$lt;p$gt;你好$lt;/p$lt;。
如果想要不進行格式化輸出,而是要輸出原始內容,則使用th:utext來代替.
Thymeleaf中所有的表達式都需要寫在指令中,指令是HTML5中的自定義屬性,在Thymeleaf中所有指令都是以th:開頭。因為表達式${user.name}是寫在自定義屬性中,因此在靜態(tài)環(huán)境下,表達式的內容會被當做是普通字符串,瀏覽器會自動忽略這些指令,這樣就不會報錯了!
<h2> <p>Name: <span th:text="${user.name}">Jack</span>.</p> <p>Age: <span th:text="${user.age}">21</span>.</p> <p>friend: <span th:text="${user.friend.name}">Rose</span>.</p> </h2>
對象.屬性名方式
${user.name} 可以寫作${user['name']}
<h2 th:object="${user}"> <p>Name: <span th:text="*{name}">Jack</span>.</p> <p>Age: <span th:text="*{age}">21</span>.</p> <p>friend: <span th:text="*{friend.name}">Rose</span>.</p> </h2>
當數據量比較多的時候,頻繁的寫user.就會非常麻煩。
首先在 h2上 用 th:object="${user}"獲取user的值,并且保存
然后,在h2內部的任意元素上,可以通過 *{屬性名}的方式,來獲取user中的屬性,這樣就省去了大量的user.前綴了
<h2 th:object="${user}"> <p>FirstName: <span th:text="*{name.split(' ')[0]}">Jack</span>.</p> <p>LastName: <span th:text="*{name.split(' ')[1]}">Li</span>.</p> </h2>
ognl表達式本身就支持方法調用
Thymeleaf中提供了一些內置對象,并且在這些對象中提供了一些方法,方便我們來調用。獲取這些對象,需要使用#對象名來引用。
一些環(huán)境相關對象
對象 作用
#ctx 獲取Thymeleaf自己的Context對象
#requset 如果是web程序,可以獲取HttpServletRequest對象
#response 如果是web程序,可以獲取HttpServletReponse對象
#session 如果是web程序,可以獲取HttpSession對象
#servletContext 如果是web程序,可以獲取HttpServletContext對象
Thymeleaf提供的全局對象:
對象 作用
#dates 處理java.util.date的工具對象
#calendars 處理java.util.calendar的工具對象
#numbers 用來對數字格式化的方法
#strings 用來處理字符串的方法
#bools 用來判斷布爾值的方法
#arrays 用來護理數組的方法
#lists 用來處理List集合的方法
#sets 用來處理set集合的方法
#maps 用來處理map集合的方法
java代碼:
@GetMapping("show3") public String show3(Model model){ model.addAttribute("today", new Date()); return "show3"; }
頁面代碼:
<p> 今天是: <span th:text="${#dates.format(today,'yyyy-MM-dd')}">2018-04-25</span> </p> ${#strings.equals('編程幫',name)} ${#session.getAttribute('map')} ${session.map}
字面值:
基本類型如:字符串、數值、布爾等,并不希望被Thymeleaf解析為變量,這個時候稱為字面值
字符串字面值:th:text="'thymeleaf'" 使用一對'引用的內容
數字字面值:th:text="2018" 數字不需要任何特殊語法, 寫的什么就是什么,而且可以直接進行算術運算
布爾字面值:th:if="true"
空字面值:<p th:text="${user == null}"></p>
<p> 你正在觀看 <span th:text="'thymeleaf'">template</span> 的字符串常量值. </p>
拼接
我們經常會用到普通字符串與表達式拼接的情況:
<span th:text="'歡迎您:' + ${user.name} + '!'"></span>
字符串字面值需要用'',拼接起來非常麻煩,Thymeleaf對此進行了簡化,使用一對|即可:
<span th:text="|歡迎您:${user.name}|"></span>
運算
<span th:text="${user.age}"></span> <span th:text="${user.age}%2 == 0"></span>
支持的算術運算符:+ - * / %
支持的比較運算:>, <, >= and <=
但是>, <不能直接使用,因為xml會解析為標簽,要使用別名。
注意 == and !=不僅可以比較數值,類似于equals的功能。
可以使用的別名:gt (>), lt (<), ge (>=), le (<=), not (!). Also eq (==), neq/ne (!=).
三元運算:<span th:text="${user.sex} ? '男':'女'"></span>
默認值: <span th:text="${user.name} ?: '二狗'"></span> ( ?:之間沒有空格 )
${}內部的是通過OGNL表達式引擎解析的,外部的才是通過Thymeleaf的引擎解析,因此運算符盡量放在${}外進行。
設置屬性值
在 Thymeleaf 模板文件中,你可以使用
th:*
(或者使用th:attr
屬性)來設置任意的 HTML5 標簽屬性的值。不僅如此,你還可以th:*-*
來同時為多個不同的標簽屬性設置相同的一個值,甚至你可以使用th:attrappend
和th:attrprepend
來追加新的值到現有的標簽屬性值中。th:attr 這種方式是不被推薦的
<!-- <div item-id="1001">Welcome to BeiJing!</div> --> <div th:item-id="${user.id}">Welcome to BeiJing!</div> <img src="logo.png" th:alt-title="LOGO圖片">
th:*
中的*
可以是 HTML5 支持的任意屬性名稱,甚至這些屬性名稱可以是自定義的
th:*-*
如果想要同時為標簽的多個不同屬性設置相同的一個值,可以使用th:*-*
的語法:th:attrappend & th:attrprepend 可以將表達式的結果分別追加到指定的屬性值之后和之前。
<!-- <button class="btn enable">購買</button> --> <button class="btn" th:attrappend="class=${outOfStock} ? ' enable' : ' disable'">購買</button> <!-- <button class="enable btn">購買</button> --> <button class="btn" th:attrprepend="class=${outOfStock} ? 'enable ' : 'disable '">購買</button>
還有兩個常用的具體附加屬性th:classappend="..."
和th:styleappend=""
。它們分別用來代替th:attrappend="class=..."
和th:attrappend="style=..."
<!-- <button class="btn enable">購買</button> --> <button class="btn" th:classappend="${outOfStock} ? ' enable' : ' disable'">購買</button>
循環(huán)/IF/SWITCH
<tr th:each="user : ${users}"> <td th:text="${user.name}">Onions</td> <td th:text="${user.age}">2.41</td> </tr> <tr th:each="user,stat : ${users}"> <td th:text="${user.name}">Onions</td> <td th:text="${user.age}">2.41</td> </tr>
stat對象包含以下屬性:
index,從0開始的角標
count,元素的個數,從1開始
size,總元素個數
current,當前遍歷到的元素
even/odd,返回是否為奇偶,boolean值
first/last,返回是否為第一或最后,boolean值
<div th:switch="${user.role}"> <p th:case="'admin'">用戶是管理員</p> <p th:case="'manager'">用戶是經理</p> <p th:case="*">用戶是別的玩意</p> </div>
JS模板
<script th:inline="javascript"> const user = /*[[${user}]]*/ {}; const age = /*[[${user.age}]]*/ 20; console.log(user); console.log(age) </script>
在script標簽中通過th:inline="javascript"來聲明這是要特殊處理的js腳本
語法結構:
const user = /*[[Thymeleaf表達式]]*/ "靜態(tài)環(huán)境下的默認值";
因為Thymeleaf被注釋起來,因此即便是靜態(tài)環(huán)境下, js代碼也不會報錯,而是采用表達式后面跟著的默認值。
鏈接表達式 @{}
@{}
是專門用來處理 URL 鏈接地址的。
不管是靜態(tài)資源的引用,還是 form 表單的請求,凡是鏈接都可以用鏈接表達式 (@{...})。鏈接表達式的形式結構如下:
無參請求:@{/xxx}
有參請求:@{/xxx(k1=v1,k2=v2)}
絕對地址:
<!-- https://fanlychie.github.io --> <p th:text="@{https://fanlychie.github.io}"></p>
頁面相對地址示例:
<!-- commons/base.html --> <p th:text="@{commons/base.html}"></p>
上下文相對地址(相對于當前的服務)示例:
<!-- /css/mian.css --> <p th:text="@{/css/mian.css}"></p>
服務器相對地址(相對于部署在同一個服務器中的不同服務)示例:
<!-- /image/upload --> <p th:text="@{~/image/upload}"></p>
參數使用示例:
<!-- /css/mian.css?v=1.0 -->
<p th:text="@{/css/mian.css(v=1.0)}"></p>
<!-- /user/order?username=fanlychie -->
<p th:text="@{/user/order(username=${session.user.name})}"></p>
<!-- /user/order?username=fanlychie&status=PAIED -->
<p th:text="@{/user/order(username=${session.user.name},status='PAIED')}"></p>
<!-- /user/fanlychie/info -->
<p th:text="@{/user/{username}/info(username=${session.user.name})}"></p>
片段表達式
~{}
可以用來引用一段公共的 HTML 代碼片段。
在 Thymeleaf 模板文件中,你可以使用
th:fragment
屬性來定義一段公共的代碼片段,然后你可以通過使用th:insert
、th:replace
屬性來將這些公共的代碼片段引入到模板文件中來。
th:insert
是直接將代碼片段插入到標簽體內
th:replace
則是用代碼片段直接替換標簽體內容。
src/main/resources/templates/base.html,通過th:fragment
屬性定義一段公共的代碼片段:
<div id="footer" th:fragment="footerFragment">© 2017 fanlychie</div>
src/main/resources/templates/index.html,通過th:insert
屬性引用一段公共的代碼片段:
<div th:insert="~{base :: footerFragment}"></div>
<div th:replace="~{base :: footerFragment}"></div>
(1)其中,
~{}
是可選的,我們可以去掉這層的包裹:<div th:insert="base :: footerFragment"></div>
(2)若 index.html 與 base.html 不在同級目錄,如 templates/commons/base.html:
<div th:insert="~{commons/base :: footerFragment}"></div> (3)使用th:fragment屬性定義代碼片段時,你還可以聲明一組參數:
<div th:fragment="crumbs(parent, child)"> <i th:text="${parent}"></i> <i th:text="${child}"></i> </div> <!-- <i>用戶中心</i> <i>我的訂單</i> --> <div th:insert="::crumbs('用戶中心', '我的訂單')"></div>
三、Thymeleaf 實戰(zhàn)應用
1、input 、textarea 賦值
//JAVA @RequestMapping(value = { "formData", "" }) public String list(HttpServletRequest request, ModelMap model) { Entity entity = xxxService.getEntity(); model.addAttribute("entity", entity); return "test.html"; }
<!-- HTML --> <input type="text" th:attr="name=${entity.name},required=${entity.propRequired}" placeholder="請輸入"/> <textarea th:text="${entity.remarks=='null'?'':entity.remarks}" placeholder="請輸入"></textarea>
2.復選框 判斷選中
//JAVA @RequestMapping(value = { "checkboxValue", "" }) public String list(HttpServletRequest request, ModelMap model) { Entity entity = xxxService.getEntity(); model.addAttribute("entity", entity); return "test.html"; }
<input type="checkbox" th:checked="${entity.prop1 eq '1'}"> aaa <input type="checkbox" th:checked="${entity.prop2 eq '1'}"> bbb
3.下拉框 動態(tài)賦值 與 回顯
//JAVA @RequestMapping(value = { "selectList", "" }) public String list(HttpServletRequest request, ModelMap model) { List<selectData> selectList = xxxService.getSelectList(); int type = xxxService.getType(); model.addAttribute("type", type); model.addAttribute("selectList", selectList); return "test.html"; }
下拉框數據填充
<select data-placeholder="請選擇" id="selectData" > <option value=" " selected>請選擇</option> <option th:each="data:${selectList}" th:value="${data.id}" th:text="${data.name}"> </option> </select>
下拉框數據填充,判斷,回顯數據
<select> <option value="" th:selected="${type eq ''}">請選擇</option> <option value="1" th:selected="${type eq 1}">字符型</option> <option value="2" th:selected="${type eq 2}">整型</option> <option value="3" th:selected="${type eq 3}">日期</option> </select>
js設置下拉框選中,回顯數據
<script type="text/javascript"> $("#selectData").ready(function() { var value= "[[${type}]]"; $("#selectData option[value= " + value + "]").prop("selected",true); }); </script>
4.循環(huán)遍歷
@RequestMapping(value = { "loopTest", "" }) public String list(HttpServletRequest request, ModelMap model) { List<Entity> dataList = xxxService.getEntityList(); Map<String,List<Entity>> dataMap = xxxService.getEntityMap(); model.addAttribute("dataList", dataList); model.addAttribute("dataMap", dataMap); return "test.html"; }
遍歷 list 數據:循環(huán)生成表格數據
<table> <head> <tr> <th>ID</th> <th>名稱</th> <th>類型</th> <th>時間</th> <th>是否可用</th> </head> <body> <tr th:each="data : ${dataList}" > <td th:text="${data.id}"></td> <td th:text="${data.name}"></td> <td th:switch="${data.type}"> <span th:case="1">字符型</span> <span th:case="2">整型</span> <span th:case="3">日期</span> </td> <td th:text="${#dates.format(data.createDate, 'yyyy-MM-dd HH:mm:ss')}"></td> <td> <span th:if="${data.usable} eq '1'"> <i class="fa fa-check"></i> </span> </td> </tr> </body> </table>
遍歷map數據
<div th:each="dataEntry,dataStat: ${dataMap}" > <div> [[${dataEntry.key}]] </div> <div th:each="data: ${dataEntry.value}"> <div> <dt>[[${data.id}]]: </dt> <dd>[[${data.name}]]</dd> </div> </div> </div>
5.超鏈接 url傳參
@RequestMapping(value = { "formData", "" }) public String list(HttpServletRequest request, ModelMap model) { Entity entity = xxxService.getEntity(); model.addAttribute("entity", entity); return "test.html"; }
<a th:href="@{test/form(id=${entity.id},name=${entity.name})}" rel="external nofollow" >超鏈接1</a> <a th:href="@{test/form?id='+${entity.id}}+'&name='+${entity.name}" rel="external nofollow" >超鏈接2</a>
springboot配合thymeleaf,調用接口不跳轉頁面只顯示文本
問題一:thymeleaf不跳轉頁面,只顯示文本index
@RequestMapping("/excel") @RestController public class OperateExcelController { @GetMapping(value = "") public String index() { //使用@RestController不能直接返回return "index",否則不會跳轉頁面,只會再頁面顯示index文本而已 return "index"; }
@RestController注解相當于@ResponseBody和@Controller合在一起的作用。在使用@RestController注解Controller時,Controller中的方法無法返回jsp頁面,或者html,配置的視圖解析器 InternalResourceViewResolver不起作用,返回的內容就是Return 里的內容。
包括在Mapping注解使用的同時使用@ResponseBody時也會出現同樣的問題。
解決方案
解決辦法①:去除@ResponseBody或將含有Rest的注解換成對應的原始注解@Controller;
@RequestMapping("/excel") @Controller public class OperateExcelController { @GetMapping(value = "") public String index() { return "index"; }
解決辦法②:不通過String返回,通過ModelAndView對象返回,上述例子可將return語句換成下面的句子,在使用ModelAndView對象返回的時候,不需要考慮有沒有@ResponseBody類似的注解。
@RequestMapping("/excel") @RestController public class OperateExcelController { @GetMapping(value = "") public ModelAndView index() { return new ModelAndView("index"); }
到此這篇關于SpringBoot 整合Thymeleaf教程及使用的文章就介紹到這了,更多相關SpringBoot 整合Thymeleaf內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
application作用域實現用戶登錄擠掉之前登錄用戶代碼
這篇文章主要介紹了application作用域實現用戶登錄擠掉之前登錄用戶代碼,具有一定參考價值,需要的朋友可以了解下。2017-11-11淺談java中String StringBuffer StringBuilder的區(qū)別
下面小編就為大家?guī)硪黄獪\談java中String StringBuffer StringBuilder的區(qū)別。小編覺得挺不錯的,現在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2016-06-06spring boot jpa寫原生sql報Cannot resolve table錯誤解決方法
在本篇文章里小編給大家整理的是關于spring boot jpa寫原生sql報Cannot resolve table錯誤的解決方法,需要的朋友學習下。2019-11-11ByteArrayOutputStream與InputStream互相轉換方式
這篇文章主要介紹了ByteArrayOutputStream與InputStream互相轉換方式,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2021-12-12