一、Thymeleaf简介
1、什么是Thymeleaf?
Thymeleaf 是一款用于渲染 XML/XHTML/HTML5 内容的模板引擎。是新一代 Java 模板引擎,它支持 HTML 原型,其文件后缀为“.html”,因此它可以直接被浏览器打开,此时浏览器会忽略未定义的 Thymeleaf 标签属性,展示 thymeleaf 模板的静态页面效果;当通过 Web 应用程序访问时,Thymeleaf 会动态地替换掉静态内容,使页面动态显示。
2、模版引擎的作用与区别?
模板引擎的作用都是将模板(页面)和数据进行整合然后输出显示,区别在于不同的模板使用不同的语法。
在使用Thymeleaf之前,首先要在页面的html标签中声明命名空间。此操作是用于避免编辑器出现html验证错误,但并非必须。即使不声明也不影响thymeleaf的使用。
3、Thymeleaf的特点
(1)Thymeleaf 在有网络和无网络的环境下皆可运行,即它可以让美工在浏览器查看页面的静态效果,也可以让程序员在服务器查看带数据的动态页面效果。这是由于它支持 html 原型,然后在 html 标签里增加额外
的属性来达到模板 + 数据的展示方式。浏览器解释 html 时会忽略未定义的标签属性,所以 thymeleaf 的模板可以静态地运行;当有数据返回到页面时,Thymeleaf 标签会动态地替换掉静态内容,使页面动态显示。
(2)Thymeleaf 开箱即用的特性。它提供标准和 Spring 标准两种方言,可以直接套用模板实现 JSTL、 OGNL 表达式效果,避免每天套模板、改 JSTL、改标签的困扰。同时开发人员也可以扩展和创建自定义的方言。
(3)Thymeleaf 提供 Spring 标准方言和一个与 SpringMVC 完美集成的可选模块,可以快速的实现表单绑定、属性编辑器、国际化等功能。
二、标准表达式语法
Thymeleaf模版引擎支持多种表达式
1、变量表达式
使用${}包裹的称为变量表达式,它具有以下功能:
(1)获取对象的属性与方法。
${person.lastName}
(2)使用内置的基本对象。
使用变量表达式还可以访问内置基本对象的属性和方法。
内置基本对象包括
#ctx:上下文对象
#vars:上下文变量
#locale:上下文的语言环境
#request:HttpServletRequest对象(仅在Web应用中可用)
#response:HttpServletResponse对象(仅在Web应用中可用)
#sesssion:HttpSession对象(仅在Web应用中可用)
#servletContext:ServletContext对象(仅在Web应用中可用)
以下2中方式,都可以获取session对象中的map属性。
${#session.getAttribute('map')}
${session.map}
(3)使用内置的工具对象
strings:字符串工具对象,常用方法有:equals、equalsIgnoreCase、length、trim、toUpperCase、toLowerCase、indexOf、substring、replace、startsWith、endsWith,contains 和 containsIgnoreCase 等;
numbers:数字工具对象,常用的方法有:formatDecimal 等;
bools:布尔工具对象,常用的方法有:isTrue 和 isFalse 等;
arrays:数组工具对象,常用的方法有:toArray、length、isEmpty、contains 和 containsAll 等;
lists/sets:List/Set 集合工具对象,常用的方法有:toList、size、isEmpty、contains、containsAll 和 sort 等;
maps:Map 集合工具对象,常用的方法有:size、isEmpty、containsKey 和 containsValue 等;
dates:日期工具对象,常用的方法有:format、year、month、hour 和 createNow 等。
例:使用内置工具对象strings判断字符串与对象的某个属性是否相等
${#strings.equals('编程帮',name)}
2、选择变量表达式
选择变量表达式与变量表达式功能基本一致,只是在变量表达式的基础上增加了与 th:object 的配合使用。当使用 th:object 存储一个对象后,我们可以在其后代中使用选择变量表达式({…})获取该对象中的属性,其中,“”即代表该对象。
例:
<div th:object="${session.user}" >
<p th:text="*{fisrtName}">firstname</p>
</div>
3、链接表达式
不管是静态资源的引用,还是 form 表单的请求,凡是链接都可以用链接表达式 (@{…})。 链接表达式的形式结构如下: 无参请求:@{/xxx} 有参请求:@{/xxx(k1=v1,k2=v2)} 例如使用链接表达式引入 css 样式表,代码如下。
<link href="asserts/css/signin.css" th:href="@{/asserts/css/signin.css}" rel="stylesheet">
4、国际化表达式
消息表达式一般用于国际化的场景。结构如下。
th:text="#{msg}"
注意:此处了解即可,我们会在后面的章节中详细介绍。
5、 片段引用表达式
片段引用表达式用于在模板页面中引用其他的模板片段,该表达式支持以下 2 中语法结构:
推荐:~{templatename::fragmentname}
支持:~{templatename::#id}
以上语法结构说明如下:
templatename:模版名,Thymeleaf 会根据模版名解析完整路径:/resources/templates/templatename.html,要注意文件的路径。
fragmentname:片段名,Thymeleaf 通过 th:fragment 声明定义代码块,即:th:fragment=“fragmentname”
id:HTML 的 id 选择器,使用时要在前面加上 # 号,不支持 class 选择器。
三、th属性
Thymeleaf 还提供了大量的 th 属性,这些属性可以直接在 HTML 标签中使用。
属性 | 描述 | 示例 |
---|---|---|
th:id | 替换HTML的id属性 | html<input id="html-id" th:id="thymeleaf-id" /> |
th:text | 文本替换,转义特殊字符 | <h1 th:text="hello,bianchengbang" >hello</h1> |
th:utext | 文本替换,不转义特殊字符 | <div th:utext="<h1>欢迎来到编程帮!</h1>" >欢迎你</div> |
th:object | 在父标签选择对象,子标签使用 *{…} 选择表达式选取值。没有选择对象,那子标签使用选择表达式和 ${…} 变量表达式是一样的效果。同时即使选择了对象,子标签仍然可以使用变量表达式。 | <div th:object="${session.user}" ><p th:text="*{fisrtName}">firstname</p></div> |
th:value | 替换 value 属性 | <input th:value = "${user.name}" /> |
th:with | 局部变量赋值运算 | <div th:with="isEvens = ${prodStat.count}%2 == 0" th:text="${isEvens}"></div> |
th:style | 设置样式 | <div th:style="'color:#F00; font-weight:bold'">编程帮 www.biancheng.net</div> |
th:onclick | 点击事件 | <td th:onclick = "'getInfo()'"></td> |
th:each | 遍历,支持 Iterable、Map、数组等。 | <table> <tr th:each="m:${session.map}"> <td th:text="${m.getKey()}"></td><td th:text="${m.getValue()}"></td> </tr></table> |
th:if | 根据条件判断是否需要展示此标签 | <a th:if ="${userId == collect.userId}"> |
th:unless | 和 th:if 判断相反,满足条件时不显示 | <div th:unless="${m.getKey()=='name'}" ></div> |
th:switch | 与 Java 的 switch case语句类似通常与 th:case 配合使用,根据不同的条件展示不同的内容 | <div th:switch="${name}"> <span th:case="a">编程帮</span> <span th:case="b">www.biancheng.net</span></div> |
th:fragment | 模板布局,类似 JSP 的 tag,用来定义一段被引用或包含的模板片段 | <footer th:fragment="footer">插入的内容</footer> |
th:insert | 布局标签;将使用 th:fragment 属性指定的模板片段(包含标签)插入到当前标签中。 | <div th:insert="commons/bar::footer"></div> |
th:replace | 布局标签;使用 th:fragment 属性指定的模板片段(包含标签)替换当前整个标签。 | <div th:replace="commons/bar::footer"></div> |
th:selected select | 选择框选中 | <select> <option>---</option> <option th:selected="${name=='a'}"> 编程帮</option> <option th:selected="${name=='b'}"> www.biancheng.net </option></select> |
th:src | 替换 HTML 中的 src 属性 | <img th:src="@{/asserts/img/bootstrap-solid.svg}" src="asserts/img/bootstrap-solid.svg" /> |
th:inline | 内联属性:该属性有 text,none,javascript 三种取值在script 标签中使用时,js 代码中可以获取到后台传递页面的对象。 | <script type="text/javascript" th:inline="javascript"> var name = /*[[${name}]]*/ 'bianchengbang'; alert(name)</script> |
th:action | 替换表单提交地址 | <form th:action="@{/user/login}" th:method="post"></form> |
四、Thymeleaf公共页面抽取
在Web项目中,通常存在一些公共页面片段(重复代码),如导航栏,侧边栏和公共的·js css等。我们可以将这些公共页面片段抽取出来,存放在一个独立的页面中,在由其他页面引用,从而消除代码重复,使页面更加简洁。
1.创建commons.html文件,编辑公共页面片段:
<div th:fragment="fragment-name" id="fragment-id">
<span>公共页面片段</span>
</div>
2.引用该页面片段,thymeleaf提供了三种引入的方式
th:insert:将代码块片段整个插入到使用了 th:insert 属性的 HTML 标签中;
th:replace:将代码块片段整个替换使用了 th:replace 属性的 HTML 标签中;
th:include:将代码块片段包含的内容插入到使用了 th:include 属性的 HTML 标签中。
<!--th:insert 片段名引入-->
<div th:insert="commons::fragment-name"></div>
<!--th:insert id 选择器引入-->
<div th:insert="commons::#fragment-id"></div>
------------------------------------------------
<!--th:replace 片段名引入-->
<div th:replace="commons::fragment-name"></div>
<!--th:replace id 选择器引入-->
<div th:replace="commons::#fragment-id"></div>
------------------------------------------------
<!--th:include 片段名引入-->
<div th:include="commons::fragment-name"></div>
<!--th:include id 选择器引入-->
<div th:include="commons::#fragment-id"></div>
3.在抽取和引入公共页面片段时传递参数
示例:
编辑一个引用时需要传入参数的页面片段
<!--使用 var1 和 var2 声明传入的参数,并在该片段中直接使用这些参数 -->
<div th:fragment="fragment-name(var1,var2)" id="fragment-id">
<p th:text="'参数1:'+${var1} + '-------------------参数2:' + ${var2}">...</p>
</div>
引用此页面片段时同时传入参数
<!--th:insert 片段名引入-->
<div th:insert="commons::fragment-name(var1='insert-name',var2='insert-name2')"></div>
<!--th:insert id 选择器引入-->
<div th:insert="commons::#fragment-id(var1='insert-id',var2='insert-id2')"></div>