Thymeleaf
- 1什么是Thymeleaf? Thymeleaf是一个现代服务器端Java模板引擎,适用于Web和独立环境,能够处理HTML,XML,JavaScript,CSS甚至纯文本。 Thymeleaf的主要目标是提供一种优雅且高度可维护的模板创建方式。为实现这一目标,它以自然模板的概念为基础,将其逻辑注入模板文件,其方式不会影响模板被用作设计原型。这改善了设计沟通,缩小了设计和开发团队之间的差距。
Thymeleaf 的特点
Thymeleaf 模板引擎具有以下特点:
- 动静结合:Thymeleaf 既可以直接使用浏览器打开,查看页面的静态效果,也可以通过 Web 应用程序进行访问,查看动态页面效果。
- 开箱即用:Thymeleaf 提供了 Spring 标准方言以及一个与 SpringMVC 完美集成的可选模块,可以快速的实现表单绑定、属性编辑器、国际化等功能。
- 多方言支持:它提供了 Thymeleaf 标准和 Spring 标准两种方言,可以直接套用模板实现 JSTL、 OGNL 表达式;必要时,开发人员也可以扩展和创建自定义的方言。
- 与 SpringBoot 完美整合:SpringBoot 为 Thymeleaf 提供了的默认配置,并且还为 Thymeleaf 设置了视图解析器,因此 Thymeleaf 可以与 Spring Boot 完美整合。
Thymeleaf 官网:https://www.thymeleaf.org/
Thymeleaf 在Github 的主页:https://github.com/thymeleaf/thymeleaf
Spring官方文档:找到我们对应的版本
新版Spring Boot启动器:https://docs.spring.io/spring-boot/docs/2.2.5.RELEASE/reference/htmlsingle/#using-boot-starter
旧版Spring Boot启动器:https://docs.spring.io/spring-boot/docs/2.0.4.RELEASE/reference/htmlsingle/#using-boot-starter
推荐博客:https://fanlychie.github.io/post/thymeleaf.html
导入依赖
<!-- 引入thymeleaf的依赖-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
html导入:
<html xmlns:th="http://www.thymeleaf.org">
#关闭thymeleaf缓存
spring.thymeleaf.cache=false
使用内置的基本对象
使用变量表达式还可以使用内置基本对象,获取内置对象的属性,调用内置对象的方法。 Thymeleaf 中常用的内置基本对象如下:
-
#ctx :上下文对象;
-
#vars :上下文变量;
-
#locale:上下文的语言环境;
-
#request:HttpServletRequest 对象(仅在 Web 应用中可用);
-
#response:HttpServletResponse 对象(仅在 Web 应用中可用);
-
#session:HttpSession 对象(仅在 Web 应用中可用);
-
#servletContext:ServletContext 对象(仅在 Web 应用中可用)。
-
例如,我们通过以下 2 种形式,都可以获取到 session 对象中的 map 属性:
${#session.getAttribute('map')} ${session.map}
除了能使用内置的基本对象外,变量表达式还可以使用一些内置的工具对象。
- 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 的 equals 方法,来判断字符串与对象的某个属性是否相等,代码如下。
${#strings.equals('编程帮',name)}
选择变量表达式
选择变量表达式与变量表达式功能基本一致,只是在变量表达式的基础上增加了与 th:object 的配合使用。当使用 th:object 存储一个对象后,我们可以在其后代中使用选择变量表达式({...})获取该对象中的属性,其中,“”即代表该对象。
<div th:object="${session.user}" > <p th:text="*{fisrtName}">firstname</p></div>
th:object 用于存储一个临时变量,该变量只在该标签及其后代中有效,在后面的内容“th 属性”中我详细介绍。
链接表达式
不管是静态资源的引用,还是 form 表单的请求,凡是链接都可以用链接表达式 (@{...})。 链接表达式的形式结构如下: 无参请求:@{/xxx} 有参请求:@{/xxx(k1=v1,k2=v2)} 例如使用链接表达式引入 css 样式表,代码如下。
<link href="asserts/css/signin.css" th:href="@{/asserts/css/signin.css}" rel="stylesheet">
国际化表达式
消息表达式一般用于国际化的场景。结构如下。
th:text="#{msg}"
注意:此处了解即可,我们会在后面的章节中详细介绍。
片段引用表达式
片段引用表达式用于在模板页面中引用其他的模板片段,该表达式支持以下 2 中语法结构:
- 推荐:~{templatename::fragmentname}
- 支持:~{templatename::#id}
以上语法结构说明如下:
- templatename:模版名,Thymeleaf 会根据模版名解析完整路径:/resources/templates/templatename.html,要注意文件的路径。
- fragmentname:片段名,Thymeleaf 通过 th:fragment 声明定义代码块,即:th:fragment="fragmentname"
- id:HTML 的 id 选择器,使用时要在前面加上 # 号,不支持 class 选择器。
hymeleaf 模板引擎支持多种表达式:
- 变量表达式:${...}
- 选择变量表达式:*{...}
- 链接表达式:@{...}
- 国际化表达式:#{...}
- 片段引用表达式:~{...}
Thymeleaf语法
th属性,常用th属性如下:
| 属性 | 描述 | 示例 |
|---|---|---|
| th:id | 替换 HTML 的 id 属性 | <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 三种取值, 在 标签中使用时,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> |
在 url 中实现参数传递
<a th:href="@{/show(id=1,name=zhagnsan)}">相对路径-传参</a>
在 url 中通过 restful 风格进行参数
<a th:href="@{/path/{id}/show(id=1,name=zhagnsan)}"> 相 对 路 径 - 传 参-restful</a>
html
<!DOCTYPE html>
<!--名称空间-->
<html lang="en" xmlns:th="http://www.thymeleaf.org"><head>
<meta charset="UTF-8">
<title>Thymeleaf 语法</title></head><body>
<h2>ITDragon Thymeleaf 语法</h2>
<!--th:text 设置当前元素的文本内容,常用,优先级不高-->
<p th:text="${thText}" />
<p th:utext="${thUText}" />
<!--th:value 设置当前元素的value值,常用,优先级仅比th:text高-->
<input type="text" th:value="${thValue}" />
<!--th:each 遍历列表,常用,优先级很高,仅此于代码块的插入-->
<!--th:each 修饰在div上,,若只想p标签遍历,则修饰在p标签上-->
<div th:each="message : ${thEach}"> <!-- 遍历整个div-p,不推荐-->
<p th:text="${message}" />
</div>
<div> <!--只遍历p,推荐使用-->
<p th:text="${message}" th:each="message : ${thEach}" />
</div>
<!--th:if 条件判断,类似的有th:switch,th:case,优先级仅次于th:each, 其中#strings是变量表达式的内置方法-->
<p th:text="${thIf}" th:if="${not #strings.isEmpty(thIf)}"></p>
<!--th:insert 把代码块插入当前div中,优先级最高,类似的有th:replace,th:include,~{} :代码块表达式 -->
<div th:insert="~{grammar/common::thCommon}"></div>
q
<!--th:utext:进行转义,列如:<p>aaa</p> 转义成aaa-->
<td th:utext="${l.getContent()}"></td>
<!--th:object 声明变量,和*{} 一起使用-->
<div th:object="${thObject}">
<p>ID: <span th:text="*{id}" /></p><!--th:text="${thObject.id}"-->
<p>TH: <span th:text="*{thName}" /></p><!--${thObject.thName}-->
<p>DE: <span th:text="*{desc}" /></p><!--${thObject.desc}-->
</div></body></html>
Controller
@Controller
public class ThymeleafController {
@RequestMapping("thymeleaf")
public String thymeleaf(ModelMap map) {
map.put("thText", "th:text 设置文本内容 <b>加粗</b>");
map.put("thUText", "th:utext 设置文本内容 <b>加粗</b>");
map.put("thValue", "thValue 设置当前元素的value值");
map.put("thEach", Arrays.asList("th:each", "遍历列表"));
map.put("thIf", "msg is not null");
map.put("thObject", new ThObject(1L, "th:object", "用来偷懒的th属性"));
return "grammar/thymeleaf";
}
}
test
<body>
<!--不转义-->
<div th:text="${msg}"></div>
<!---转义-->
<div th:utext="${msg}"></div>
<!--使用each-->
<div th:each="user:${msg2}" th:text="${user}"></div>
<!--或者使用行内元素-->
<div th:each="user2:${msg2}">[[${user2}]]</div>
</body>
ControllerTest
@Controller
public class ControllerTest {
@RequestMapping("test")
public String testTest(Model model){
model.addAttribute("msg","<h1>Hello,Spring Boot</h1>");
model.addAttribute("msg2", Arrays.asList("aaa","bbb"));
return "test";
}
}