一、简介
目前 Java Web 开发推荐使用模板引擎,不建议使用 JSP 页面
JSP缺点:本质上就是Servlet,需要后台编译,耗时,效率低
模板引擎:不需要编译,速度快
常见的模板引擎:Freemarker、Velocity、Thymeleaf 等
SpringBoot 推荐使用 Thymeleaf,且默认不支持 JSP,因为 JSP 必须要打包war包才二、使用步骤
2.1、添加 Thymeleaf 依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
2.2、将 HTML 页面放到 templates 目录中
templates 目录下的 HTML 页面默认不能被直接访问,需要通过controller 来访问,由 thymeleaf 来渲染,自动添加前缀和后缀。
@RequestMapping("/test1")
public String test01(Model model){
model.addAttribute("name","alice");
return "success";
}
2.3、使用Thymeleaf编写一个 success.html
<!DOCTYPE html>
<!--导入thymeleaf的命名空间-->
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<h2>Success!</h2>
<!--使用th:text属性,设置元素的文本,表达式${}可以获取作用域中的属性-->
<div th:text="${name}"></div>
</body>
</html>
修改配置,使得页面修改立即生效
#禁用thymeleaf的缓存,使得修改页面马上生
spring.thymeleaf.cache=false
备注:还需要开启IDEA的自动编译,IDEA默认是不自动编译
Settting——>搜索Compiler——>Build Project Automatically
Help——>Find Action——>搜索Registry——>勾选compiler.automake…
2.4、测试结果
打开浏览器,在浏览器地址栏中输入:
http://localhost:8082/test1 ,查看结果如下:
三、语法规则
3.1、常用属性
• th:text、th:utext 设置元素中的文本内容 th:text对特殊字符进行转义,等价于内联方式[[
]
]
t
h
:
u
t
e
x
t
对
特
殊
字
符
不
进
行
转
义
,
等
价
于
内
联
方
式
[
(
{ }]] th:utext对特殊字符不进行转义,等价于内联方式[(
]]th:utext对特殊字符不进行转义,等价于内联方式[({ })]
• th:html原生属性 用来替换指定的html原生属性的值
• th:if、th:unless、th:switch、th:case 条件判断,类似于c:if
• th:each 循环,类似于c:forEach
• th:object、th:field 用于表单数据对象的绑定,将表单绑定到Controller的一个JavaBean参数,常与th:field一起使用 需要和*{}选择表达式配合使用
• th:fragment 声明代码片段,常用于页面头部和尾部的引入
• th:include、th:insert、th:replace 引入代码片段,类似于jsp:include 三者的区别:
th:include 保留自己的标签,不要th:frament的标签(Thymeleaf 3.0中不推荐使用)
th:insert 保留自己的标签,保留th:frament的标签
th:replace 不要自己的标签,保留th:frament的标签
3.2、表达式
• ${} 变量表达式 获取对象的属性、方法 使用内置的基本对象,如session、application等 使用内置的工具对象,如#strings、#dates、#arrays、#lists、#maps等
• *{}选择表达式(星号表达式) 需要和th:object配合使用,简化获取对象的属性
• @{} url表达式 定义url
• 运算符 eq gt le == != 三目运算符
四、用例示范
4.1、编写相关 HTML 页面
定义两个片段 footer.html 和 header.html,每个页面都可以引用
<!--定义 footer.html-->
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<body>
<!--th:fragment-->
<footer th:fragment="copy">
这是页面的底部,版权
</footer>
</body>
</html>
<!--定义header.html-->
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<body>
<!--th:fragment-->
<header th:fragment="head">
这是页面的头部,导航
</header>
</body>
</html>
编写 result.html 页面
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<!--th:text ;th:utext-->
<div th:text="${hello}">aaa</div>
<div th:utext="${hello}">bbb</div>
<!--使用内联的方式,可以再文本的前后添加内容-->
<div>[[${hello}]]aaa</div>
<div>[(${hello})]bbb</div>
<!--th:html 原生属性-->
<div id="div1" title="这是一个div" th:id="${id}" th:title="${title}"></div>
<!--th:if、th:unless、th:switch/th:case-->
<!--if判断-->
<p th:if="${age > 18}">成年</p>
<!--跟if相反的判断-->
<p th:unless="${age < 18}">成年</p>
<!--th:switch switch条件判断-->
<p th:switch="${role}">
<span th:case="admin">管理员</span>
<span th:case="teacher">老师</span>
<span th:case="student">学生</span>
<span th:case="*">其他</span>
</p>
<!--th:each 循环-->
<ul>
<li th:each="name:${names}" th:text="${name}"></li>
<!--内联的方式-->
<li th:each="name:${names}">[[${name}]]</li>
</ul>
<!--th:object th:field 用于表单数据对象的绑定,将绑定到controller的一个javaBean参数,常与th:field一起使用-->
<!--需要和 *{} 选择表达式配合使用-->
<h3>修改用户信息</h3>
<form action="modify" method="post" th:object="${user}">
编号:<input type="text" th:field="*{id}" readonly><br>
姓名:<input type="text" th:field="*{name}"><br>
年龄:<input type="text" th:field="*{age}"><br>
<input type="submit" value="修改">
</form>
<!--th:fragment 用来声明代码片段,常用于页面头部和尾部的引入-->
<!--th:include 引入代码片段,th:insert th:replace-->
<!--表示需要去引入include下面的header.html中的fragment=head的代码片段-->
<div th:include="include/header::head"></div>
<div th:insert="include/footer::copy"></div>
<div th:replace="include/header::head"></div>
</body>
</html>
编写 list.html 页面
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>Title</title>
<!--引入 css-->
<link rel="stylesheet" th:href="@{/css/style.css}">
</head>
<body>
<!--获取对象的属性和方法-->
<div th:text="${person.name}"></div>
<div th:text="${person['age']}"></div>
<div th:text="${persons[1].name}"></div>
<div th:text="${persons.size()}"></div>
<div>元素的个数:[[${persons.size()}]]</div>
<div th:text="${persons.get(2).name}"></div>
<hr>
<!--使用内置的基本对象-->
<div th:text="${session.sex}"></div>
<div th:text="${application.hobby}"></div>
<hr>
<!--使用内置的工具对象-->
<div th:text="${#strings.startsWith(person.name,'s')}"></div>
<div th:text="${#strings.substring(person.name,1,2)}"></div>
<div th:text="${#strings.length(person.name)}"></div>
<div th:text="${#dates.createNow()}"></div>
<div th:text="${#dates.create(2019,2,14)}"></div>
<div th:text="${#dates.format(birthday,'yyyy-MM-dd HH:mm:ss')}"></div>
<hr>
<!--通过基本对象获取对象属性值-->
<div th:text="${person.id}"></div>
<div th:text="${person.name}"></div>
<div th:text="${person.age}"></div>
<hr>
<!--*{}选择表达式 来获取对象值-->
<div th:object="${person}">
<div th:text="*{id}"></div>
<div th:text="*{name}"></div>
<div th:text="*{age}"></div>
</div>
<hr>
<!--@{} url表达式-->
<a href="#" th:href="@{/findUser(username=${person.name})}">查询用户信息</a><br>
<a href="product/list.html" th:href="@{/product/list}">商品列表</a>
<hr>
<!--引入js-->
<script th:src="@{/js/common.js}"></script>
<hr>
<!--运算符-->
性别:<input type="radio" name="sex" value="male" th:checked="${session.sex eq 'male'}">男
<input type="radio" name="sex" value="female" th:checked="${session.sex eq 'female'}">女
<div th:if="${address == null}">未找到地址信息</div>
<div th:text="${persons.size() >= 2 ? '大于等于2个' : '小于2个'}"></div>
</body>
</html>