SpringBoot整合thymeleaf
- 1.Thymeleaf 简介
- 2. 为什么使用 Thymeleaf
- 3. 第一个 Thymeleaf 模板页
- 4 语法
- 5. Thymeleaf引用静态资源
1.Thymeleaf 简介
1.1 概述
Thymeleaf
是一个跟 Velocity
、FreeMarker
类似的模板引擎,它可以完全替代 JSP
。相较与其他的模板引擎,它有如下三个极吸引人的特点
- Thymeleaf 在有网络和无网络的环境下皆可运行,即它可以让美工在浏览器查看页面的静态效果,也可以让程序员在服务器查看带数据的动态页面效果。这是由于它支持 html 原型,然后在 html 标签里增加额外的属性来达到模板 + 数据的展示方式。浏览器解释 html 时会忽略未定义的标签属性,所以 thymeleaf 的模板可以静态地运行;当有数据返回到页面时,Thymeleaf 标签会动态地替换掉静态内容,使页面动态显示。
- Thymeleaf 开箱即用的特性。它提供标准和 Spring 标准两种方言,可以直接套用模板实现 JSTL、 OGNL 表达式效果,避免每天套模板、改 JSTL、改标签的困扰。同时开发人员也可以扩展和创建自定义的方言。
- Thymeleaf 提供 Spring 标准方言和一个与 SpringMVC 完美集成的可选模块,可以快速的实现表单绑定、属性编辑器、国际化等功能。
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 引入依赖
主要增加 spring-boot-starter-thymeleaf
和 nekohtml
这两个依赖
-
spring-boot-starter-thymeleaf
:Thymeleaf
自动配置 -
nekohtml
:允许使用非严格的 HTML 语法
3.2 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.2.2.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.zysheep</groupId>
<artifactId>spring-boot-thymeleaf</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>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-thymeleaf</artifactId>
</dependency>
<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>
<exclusions>
<exclusion>
<groupId>org.junit.vintage</groupId>
<artifactId>junit-vintage-engine</artifactId>
</exclusion>
</exclusions>
</dependency>
<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>
3.3 在 application.yml 中配置 Thymeleaf
###ThymeLeaf配置
spring:
thymeleaf:
cache: false # 开发时关闭缓存,不然没法看到实时页面
#模板的模式,支持 HTML, XML TEXT JAVASCRIPT
mode: HTML5 # 用非严格的 HTML
#编码 可不用配置
encoding: UTF-8
#内容类别,可不用配置
servlet:
content-type: text/html
#Tomcat 服务
server:
port: 80
3.4 创建测试用 JavaBean
创建一个测试效果的 JavaBean
,简单封装一下即可
public class User implements Serializable {
private String username;
private Integer age;
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
}
3.5 创建测试用 Controller
创建一个 Controller
,造一些测试数据并设置跳转
@Controller
public class MainController {
@RequestMapping(value = {"/","thymeleaf/index"},method = RequestMethod.GET)
public String index(Model model){
User user = new User();
user.setUsername("zysheep");
user.setAge(20);
model.addAttribute("user",user);
return "index";
}
}
3.6 创建测试页面
在 templates
目录下创建 index.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>
修改 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">
3.7 测试访问
启动成功后,访问:http://localhost/thymeleaf/index 即可看到效果
4 语法
4.1 标签使用
th:text 基础信息输出
HTML代码:
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>th:text</title>
</head>
<body>
<span th:text="${user.username}">小明</span>
</body>
</html>
Java代码:
@Data
@AllArgsConstructor
@NoArgsConstructor
public class User implements Serializable {
private String username;
private Integer age;
}
@Controller
public class ThyymeleafController {
/**
* @param Model model
* @return String
* @author Administrator
* @throws
* @date 2020/3/18 10:59
*/
@GetMapping("/")
public String index(Model model){
User user = new User();
user.setUsername("伽罗");
user.setAge(21);
model.addAttribute("user",user);
return "th-text";
}
}
th:utext html内容输出
使用"th:text"
是对内容的原样输出,使用“th:utext”
可以进行html标签输出。
Java代码:
@RequestMapping("/eat")
public ModelAndView eat() {
ModelAndView modelAndView = new ModelAndView("/cat");
modelAndView.addObject("data", "<span style='color:red'>老王是吃货</span>");
return modelAndView;
}
HTML代码:
<h4 th:text="'th:text '+${data}"></h4>
<h4 th:utext="'th:utext '+${data}"></h4>
th:if, th:unless 条件判断
th:if为满足条件的业务处理,th:unless正好相反,是除去的意思。
<span th:if="${age > 18}">
成年
</span>
<span th:unless="${age > 18}">
未成年
</span>
th:switch, th:case 多条件判断
<div th:switch="${age}">
<span th:case="18">18岁</span>
<span th:case="19">19岁</span>
<spa th:case="*">其他</spa>
</div>
注意 :默认选项使用th:case="*" 指定。
th:each 循环
<div th:each="name,item:${names}">
<span th:text="${item.count}"></span>
<span th:text="${name}"></span>
</div>
@RequestMapping("/")
public ModelAndView index() {
ArrayList<String> names = new ArrayList<>();
names.add("java");
names.add("golang");
names.add("nodejs");
ModelAndView modelAndView = new ModelAndView("/index");
modelAndView.addObject("names",names);
return modelAndView;
}
其中item
为每行的详细值,key
值如下:
- index 下标,从0开始
- count 第x个,从1开始
- size 这个集合的大小
- current 当前行的值
th:fragment、th:insert、th:replace、th:include 代码片段复用
- th:fragment标签是声明代码片段,用于解决代码复用的问题,好比Java程序写的公用代码一样,每个需要的地方都可以直接调用;
- th:insert 引用fragment的代码,保留自己的主标签;
- th:replace 引用fragment的代码,不保留自己的主标签;
- th:include 使用类似th:replace,Thymeleaf3.0之后不推荐使用;
footer.html页面代码:
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
</head>
<body>
<div th:fragment="copyright">
© 著作权归 老王 所有
</div>
<div th:fragment="about">
关于
</div>
<div th:fragment="links">
CCTV
</div>
</body>
</html>
声明了两个代码片段,copyright
和about
。
cat.html
页面代码:
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
</head>
<body>
<div th:replace="footer :: copyright"></div>
<div th:insert="footer :: about"></div>
<div th:include="footer :: links"></div>
</body>
</html>
其中第一个div引用了footer.html 的 copyright 代码片段,第二个div引用了 footer.html 的 about 代码片段。
双冒号的理解: 其中使用“::”双冒号来完成对页面片段的引用,有点像php里面的语法,使用双冒号来表示对类的静态属性和方法进行直接引用。
总结: 可以很清晰的看出th:insert
、th:replace
、th:include
之间的区别,在于是否保留自己的主标签,th:include
在3.0之后已经不推荐使用了,可以使用th:replace
标签替代。
fragment代码传参
使用fragment
我们是可以在html
代码中传参的,比如我们定义了一个top.html
其中有一个“欢迎XXX”的提示,而这个人名XXX就是需要动态传递的,这样我们可以最大程度的完成代码的复用,这个时候就是一个很好的使用场景,我们需要这样做。
页面main.html代码:
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:th="http://www.thymeleaf.org"
>
<head>
<meta charset="UTF-8">
</head>
<body>
<div th:replace="footer :: webcome('老王')"></div>
</body>
</html>
页面top.html
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:th="http://www.thymeleaf.org"
>
<head>
<meta charset="UTF-8">
</head>
<body>
<div th:fragment="webcome(about)">
<span th:text="'欢迎:'+${about}"></span>
</div>
</body>
</html>
th:with 定义局部变量
页面代码:
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:th="http://www.thymeleaf.org"
>
<head>
<meta charset="UTF-8">
</head>
<body>
<div th:with="sum=4-2">
<span th:text="${sum}"></span>
</div>
</body>
</html>
页面输出结果:2
th:remove 删除标签
th:remove
用于html代码的删除,th:remove
值有五个:
-
all
删除本段所有代码 -
body
删除主标签内的所有元素 -
tag
删除主标签,保留主标签所有的元素 -
all-but-first
保留主标签和第一个元素,其他全部删除 -
none
不删除任何标签
其他标签
-
th:style 定义样式
-
th:onclick 点击事件
-
th:href 赋值属性href
-
th:value 赋值属性value
-
th:src 赋值src
-
th:action 赋值属性action
-
th:id 赋值属性id
-
th:attr 定义多个属性
-
th:object 定义一个对象
-
th:field 表单字段绑定。
-
th:href 定义超链接。
-
th:id div 标签中的ID 声明,类似HTML 标签中的归属性。
-
th:if 条件判断语句。
-
th:include 布局标签,替换内容到引入文件。
4.2 表达式使用
4.2.1 简单表达式
- 变量表达式:${…}
- 选择变量表达式:*{…}
- 消息表达式:#{…}
- 链接表达式:@{…}
- 片段表达:~{…}
4.2.2 数据的类型
- 文字:‘one text’, ‘Another one!’,…
- 数字文字:0, 34, 3.0, 12.3,…
- 布尔文字:true, false
- NULL文字:null
- 文字标记:one, sometext, main,…
4.2.3. 文本操作
- 字符串拼接:+
- 字面替换:|The name is ${name}|
4.2.4 算术运算
- 二进制运算符:+, -, *, /, %
- 减号(一元运算符):-
4.2.5 布尔运算
- 二进制运算符:and, or
- 布尔否定(一元运算符):!, false
4.2.6 条件运算符
- 比较值:>, <, >=, <=
- 相等判断: ==, !=
4.2.7 条件判断
- 如果-然后:(if) ? (then)
- 如果-然后-否则:(if) ? (then) : (else)
- 违约:(value) ?: (defaultvalue)
4.3 表达式使用实例
4.3.1 变量表达式 ${…}
变量表达式的使用,我们前面的代码已经见到了,``是我们平常开发中最常用的表达式,用于把后台Java类的动态数据,映射到页面,例如:
Java代码:
public ModelAndView index() {
ModelAndView modelAndView = new ModelAndView("/cat");
modelAndView.addObject("data", "hello world!");
return modelAndView;
}
HTML代码:
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
</head>
<body>
<span th:text="${data}"></span>
</body>
</html>
4.3.2 选择表达式 *{…}
选择表达式相当于选择了一个对象,在使用的时候不在需要这个对象的前缀,直接使用属性的key进行内容展示,代码如下:
<div th:object="${user}">
<span th:text="${user.username}"></span>
<span th:text="*{age}"></span>
<span th:text="${#dates.format(user.createTime, 'yyyy-MM-dd HH:mm:ss')}"></span>
</div>
最终效果:
伽罗 21 2020-03-18 14:09:22
总结 : *{age} = ${user.age}只是省去了“user.”前缀,效果都是一样的。
4.3.3 链接表达式 @{…}
用于转换url
,代码如下:
<a th:href="@{/footer(id=666,name=laowang)}">链接</a>
最终呈现的效果:
<a href="/footer?id=666&name=laowang">链接</a>
链接表达式,可以传递参数,用逗号分隔。服务器根相对路径:@{~/path/to/something}
4.3.4 文本操作
文本操作分为两个:文本拼加、文本替换
文本拼加 :
<span th:text="'我叫'+${name}"></span>
文本替换 : 文本替换的语法:|内容${tag}|
<span th:text="|我叫${name},是一名开发工程师。|"></span>
4.3.5 三元表达式
<tr th:class="${row.even}? 'even' : 'odd'">
4.3.6 双括号作用
<p th:text="${val}">...</p>
结果:
<p>1234567890</p>
<p>1,234,567,890</p>
4.3.7 嵌入文本标签
虽然标准的标签几乎可以满足所有的业务场景,但某些情况我们更喜欢直接写入HTML文本,例如:
<p>Hello, [[${name}]]</p>
嵌入文本有两种写法“[[…]]”和“[(…)]”,分别的作用就像th:text 和 th:utext 一样,例如:
<p>
[[${name}]]
</p>
<p>
[(${name})]
</p>
4.4 表达式对象概述
4.4.1 表达式基本对象
#ctx: 操作当前上下文.
#vars: 操作上下文变量.
#request: (仅适用于Web项目) HttpServletRequest对象.
#response: (仅适用于Web项目) HttpServletResponse 对象.
#session: (仅适用于Web项目) HttpSession 对象.
#servletContext: (仅适用于Web项目) ServletContext 对象.
4.4.2 表达式实用工具类
#execInfo: 操作模板的工具类,包含了一些模板信息,比如:${#execInfo.templateName} .
#uris: url处理的工具
#conversions: methods for executing the configured conversion service (if any).
#dates: 方法来源于 java.util.Date 对象,用于处理时间,比如:格式化.
#calendars: 类似于 #dates, 但是来自于 java.util.Calendar 对象.
#numbers: 用于格式化数字.
#strings: methods for String objects: contains, startsWith, prepending/appending, etc.
#objects: 普通的object对象方法.
#bools: 判断bool类型的工具.
#arrays: 数组操作工具.
#lists: 列表操作数据.
#sets: Set操作工具.
#maps: Map操作工具.
#aggregates: 操作数组或集合的工具.
#dates 日期函数。
#lists 列表函数。
#arrays 数组函数。
#strings 字符串函数。
#numbers 幸生字函捷生。
#ca lendars 日历函数。
#objects 对象函数。
#bools 逻辑函数。
5. Thymeleaf引用静态资源
Spring Boot
在Thymeleaf
结构模块很好提供了静态资源的引用方法
th:[href | src]@{资源在static下的目录}, 如:@{lib/jquery.js},不用填写默认的static文件夹
案例
- 资源目录结构
-
templates
目录下的ws.html
可以这样引用static
下的资源文件
<!DOCTYPE html>
<html lang="en" xmlns:th="https://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>xxx</title>
<link rel="stylesheet" type="text/css" th:href="@{css/ws.css}"/>
</head>
<body>
<!-- 导入库 -->
<script th:src="@{lib/sockjs.min.js}"></script>
<script th:src="@{lib/stomp.min.js}"></script>
<script th:src="@{lib/jquery.js}"></script>
<script th:src="@{js/ws.js}"></script>
</body>
</html>
使用原始的相对路径的话,则为 href="…/static/css/ws.css", src="…/static/lib/jquery.js" 注意:使用Thymeleaf的引用方法,只有运行项目才有效。普通打开HTML无法解析。