本文主要内容:
1、Thymeleaf简介
Thymeleaf
是一个跟Velocity、FreeMarker类似的模板引擎,它完全可以代替JSP。相比较于其他的模板引擎,它具有如下三个吸引人的特点:
- Thymeleaf在有网络和无网络的环境下即可运行,它即可用让美工在浏览器查看页面的静态效果,也可以让程序员在服务器查看带数据的动态效果。这是由于它支持HTML原型,然后在HTML标签里增加额外的属性来达到模板+数据的展示方式。浏览器解析HTML时会忽略未定义的标签属性,所以Thymeleaf的模板可以静态的运行;当有数据返回到页面时,Thymeleaf标签会动态地替换掉静态内容,使页面动态显示。
- Thymeleaf开箱即用的特性。他提供标准和Spring 标准两种方言,可以直接套用模板实现JSTL、OGNL表达式效果,避免每天套用模板、改JSTL、改标签的困扰,同时开发人员可以扩展和创建自定义的方言。
- Thymeleaf提供Spring标准方言和一个与SpringMVC完美集成的可选模板,可以快速地实现表单绑定、属性编辑器、国际化等功能。
如:<span th:text="${username}">张三</span>
静态时,th:text="${username}" 被忽略,显示“张三”,动态时,th:text="${username}" 加载成功,覆盖 “张三”
2、为什么使用Thymeleaf
如果希望以Jar形式发布模块,则尽量不要使用JSP知识,这是因为JSP在内嵌的Servlet容器上运行有一些问题(内嵌Tomcat、Jetty不支持Jar形式运行JSP,Undertow不支持JSP)。
Spring Boot中推荐使用Thymeleaf作为模板引擎,这是因为Thymeleaf提供了完美的Spring MVC支持。
Spring Boot提供了大量的模板引擎,包括:
- FreeMarker
- Groovy
- Mustache
- Thymeleaf
- Velocity
- Beetl(官网号称最快的模板引擎)
3、第一个Thymeleaf模板页
3.1 创建项目
直接看图,图中有标注
此时,项目就创建完毕了。
3.2 相关配置
此处建议添加一个依赖:nekohtml,其作用主要是允许使用非严格的 HTML 语法。
在pom.xml中添加以下依赖即可添加nekohtml依赖:
<!--提供非严格HTML模式支持-->
<dependency>
<groupId>net.sourceforge.nekohtml</groupId>
<artifactId>nekohtml</artifactId>
<version>1.9.22</version>
</dependency>
完整的pom.xml如下所示:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.1.13.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.cxhit</groupId>
<artifactId>hello-spring-boot-thymeleaf</artifactId>
<version>1.0.0-SNAPSHOT</version>
<name>hello-spring-boot-thymeleaf</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<!--thymeleaf模板引擎-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<!--提供非严格HTML模式支持-->
<dependency>
<groupId>net.sourceforge.nekohtml</groupId>
<artifactId>nekohtml</artifactId>
<version>1.9.22</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
修改**application.properties
为application.yml
**,配置 Thymeleaf
spring:
thymeleaf:
cache: false #开发时关闭缓存,不然没法实时看到页面
mode: LEGACYHTML5 #用非严格的HTML(标签不必严格遵守W3C标准)
encoding: UTF-8
servlet:
content-type: text/html #内容类型为HTML
3.3 创建测试用JavaBean
如下:
源码如下:
package com.cxhit.hello.spring.boot.thymeleaf.entity;
import java.io.Serializable;
/*实现序列化接口*/
public class User implements Serializable {
private String username;
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
}
3.4 创建测试用Controller
如下:
package com.cxhit.hello.spring.boot.thymeleaf.controller;
import com.cxhit.hello.spring.boot.thymeleaf.entity.User;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
@Controller
public class MainController {
@RequestMapping(value = {"","index"},method = RequestMethod.GET)
public String index(Model model){
User user = new User();
user.setUsername("张三");
model.addAttribute("user",user);
return "index";
}
}
3.5 创建测试页面
首选创建一个HTML页面,如下:
修改前面HTML标签用于引入Thymeleaf引擎,这样才可以在其他标签中使用th:*语法,声明如下:
<!DOCTYPE html SYSTEM "http://www.thymeleaf.org/dtd/xhtml1-strict-thymeleaf-spring4-4.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:th="http://www.thymeleaf.org">
完整的HTML代码如下:
<!DOCTYPE html SYSTEM "http://www.thymeleaf.org/dtd/xhtml1-strict-thymeleaf-spring4-4.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:th="http://www.thymeleaf.org">
<html>
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<span th:text="${user.username}" >李四</span>
</body>
</html>
3.6 测试结果
如果直接访问,显示“李四”,如果启动Spring Boot访问,显示“张三”,如下:
4、Thymeleaf常用语法
4.1 引入 Thymeleaf
修改 html 标签用于引入 thymeleaf 引擎,这样才可以在其他标签里使用 th:*
语法,这是下面语法的前提。
<!DOCTYPE html SYSTEM "http://www.thymeleaf.org/dtd/xhtml1-strict-thymeleaf-spring4-4.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:th="http://www.thymeleaf.org">
4.2 获取变量值
<p th:text="'Hello!, ' + ${name} + '!'" >name</p>
可以看出获取变量值用 $
符号,对于javaBean的话使用 变量名.属性名
方式获取,这点和 EL
表达式一样.
另外 $
表达式只能写在th标签内部,不然不会生效,上面例子就是使用 th:text
标签的值替换 p
标签里面的值,至于 p
里面的原有的值只是为了给前端开发时做展示用的.这样的话很好的做到了前后端分离.
4.3 引入 URL
Thymeleaf 对于 URL 的处理是通过语法 @{…}
来处理的
<a th:href="@{http://www.baidu.com}">绝对路径</a>
<a th:href="@{/}">相对路径</a>
<a th:href="@{css/bootstrap.min.css}">Content路径,默认访问static下的css文件夹</a>
类似的标签有:th:href
和 th:src
4.4 字符串替换
很多时候可能我们只需要对一大段文字中的某一处地方进行替换,可以通过字符串拼接操作完成:
<span th:text="'Welcome to our application, ' + ${user.name} + '!'">
一种更简洁的方式是:
<span th:text="|Welcome to our application, ${user.name}!|">
当然这种形式限制比较多,|…|中只能包含变量表达式${…},不能包含其他常量、条件表达式等。
4.5 运算符
在表达式中可以使用各类算术运算符,例如+, -, *, /, %
th:with="isEven=(${prodStat.count} % 2 == 0)"
逻辑运算符>, <, <=,>=,==,!=都可以使用,唯一需要注意的是使用<,>时需要用它的HTML转义符:
th:if="${prodStat.count} > 1"
th:text="'Execution mode is ' + ( (${execMode} == 'dev')? 'Development' : 'Production')"
4.6 条件
if/unless
Thymeleaf 中使用 th:if
和 th:unless
属性进行条件判断,下面的例子中,标签只有在 th:if
中条件成立时才显示:
<a th:href="@{/login}" th:unless=${session.user != null}>Login</a>
th:unless
于 th:if
恰好相反,只有表达式中的条件不成立,才会显示其内容。
switch
Thymeleaf 同样支持多路选择 Switch 结构:
<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>
默认属性 default 可以用 * 表示:
<div th:switch="${user.role}">
<p th:case="'admin'">User is an administrator</p>
<p th:case="#{roles.manager}">User is a manager</p>
<p th:case="*">User is some other thing</p>
</div>
4.7 循环
渲染列表数据是一种非常常见的场景,例如现在有 n 条记录需要渲染成一个表格,该数据集合必须是可以遍历的,使用 th:each
标签:
<body>
<h1>Product list</h1>
<table>
<tr>
<th>NAME</th>
<th>PRICE</th>
<th>IN STOCK</th>
</tr>
<tr th:each="prod : ${prods}">
<td th:text="${prod.name}">Onions</td>
<td th:text="${prod.price}">2.41</td>
<td th:text="${prod.inStock}? #{true} : #{false}">yes</td>
</tr>
</table>
<p>
<a href="../home.html" th:href="@{/}">Return to home</a>
</p>
</body>
可以看到,需要在被循环渲染的元素(这里是)中加入 th:each
标签,其中 th:each="prod : ${prods}"
意味着对集合变量 prods
进行遍历,循环变量是 prod
在循环体中可以通过表达式访问。