Thymeleaf 初体验
# 320.Thymeleaf 初体验
接下来我们来到视图解析与模板引擎部分。
# 前言
所谓视图解析,就是 SpringBoot 处理完请求后,跳转要某个页面的过程。
在 SpringMVC 中,经常是用转发和重定向到一个 JSP 页面;
但 SpringBoot 默认打包方式是 jar,这是一个压缩包,JSP 不支持在压缩包内编译;因此 SpringBoot 是不支持 JSP 的,要实现页面跳转的功能,需要引入第三方模板引起技术实现页面渲染(其实 JSP 也是一种模板引擎)
SpringBoot 支持 freemarker,groovy-templates,thymeleaf 等模板引擎(可以在官网文档的 starter (opens new window) 中看到),这里我们讲讲 Thymeleaf
# Thymeleaf
Thymeleaf 是什么呢?根据 官网 (opens new window) 的描述
Thymeleaf is a modern server-side Java template engine for both web and standalone environments.
大意:Thymeleaf 是一个现代化的,服务端的 Java 模板引擎
优点:既然是面向后端,那么语法就挺简单的;
缺点:性能不是很高,如果是高并发,可以考虑前后端分离的方式来做
语法:使用的是自然语言的语法,和 HTML 很类似,例如:
<table>
<thead>
<tr>
<th th:text="#{msgs.headers.name}">Name</th>
<th th:text="#{msgs.headers.price}">Price</th>
</tr>
</thead>
<tbody>
<tr th:each="prod: ${allProducts}">
<td th:text="${prod.name}">Oranges</td>
<td th:text="${#numbers.formatDecimal(prod.price, 1, 2)}">0.99</td>
</tr>
</tbody>
</table>
2
3
4
5
6
7
8
9
10
11
12
13
14
官方文档地址:Documentation - Thymeleaf (opens new window)
# 基本语法
1、表达式(用来取值的)
表达式名字 | 语法 | 用途 |
---|---|---|
变量取值 | ${...} | 获取请求域、session 域、对象等值 |
选择变量 | **{...} * | * 获取上下文对象值(例如定义了一个 Person 对象)* |
消息 | #{...} | 获取国际化等值 |
链接 | @{...} | 生成链接(会自动加上项目的地址) |
片段表达式 | ~{...} | 类似 jsp: include 的作用,引入公共页面片段 |
2、字面量
- 文本值: 'one text' , 'Another one!' ,…
- 数字: 0 , 34 , 3.0 , 12.3 ,…
- 布尔值: true , false
- 空值: null
- 变量: one,two,.... 变量不能有空格
3、文本操作:字符串拼接: +, 变量替换: |The name is ${name}|
4、数学运算:运算符: + , - , * , / , %
5、布尔运算:运算符: and , or,一元运算: ! , not
6、比较运算:比较: > , < , >= , <= ( gt , lt , ge , le ) 等式: == , != ( eq , ne )
7、条件运算
- If-then: (if) ? (then)
- If-then-else: (if) ? (then) : (else),三元运算
- Default: (value) ?: (defaultvalue)
8、特殊操作:无操作: _
# 设置属性值-th: attr
设置单个标签的属性值:在标签里用 th:attr
属性,例如第 4 行
<form action="subscribe.html" th:attr="action=@{/subscribe}">
<fieldset>
<input type="text" name="email" />
<input type="submit" value="Subscribe!" th:attr="value=#{subscribe.submit}"/>
</fieldset>
</form>
2
3
4
5
6
默认是第 4 行,会计算出 value 的属性值,然后替换掉属性 value 的值。原先 value 的值相当于是默认值。
设置多个值
<img src="../../images/gtvglogo.png" th:attr="src=@{/images/gtvglogo.png},title=#{logo},alt=#{logo}" />
也可以用 th:value
的写法替代上面的写法:
<input type="submit" value="Subscribe!" th:value="#{subscribe.submit}"/>
<form action="subscribe.html" th:action="@{/subscribe}">
2
所有 h5 兼容的标签写法,参考 Tutorial: Using Thymeleaf (opens new window)
# 迭代
<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>
2
3
4
5
<tr th:each="prod,iterStat : ${prods}" th:class="${iterStat.odd}? 'odd'">
<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>
2
3
4
5
# 条件运算
<a href="comments.html"
th:href="@{/product/comments(prodId=${prod.id})}"
th:if="${not #lists.isEmpty(prod.comments)}">view</a>
2
3
<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>
2
3
4
5
如果一个标签内写了多个属性,那么谁会生效呢?这就得提到属性的优先级了,参考文档 10 Attribute Precedence (opens new window)
# 引入 Thymeleaf
在 pom.xml 中引入 starter:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
2
3
4
引入之后,就会自动好了,通过自动配置类 ThymeleafAutoConfiguration
;这个类会帮我们放几个组件(通过几个方法,上面加了@Bean 注解):
SpringTemplateEngine
:模板引擎ThymeleafViewResolver
:视图解析器
我们只需开发页面即可。
我们在使用 SpringMVC (opens new window) 的时候,配置 视图解析器 (opens new window) 时要配置前缀和后缀等;Thymeleaf 也要配置,不过已经有了默认配置,在 ThymeleafProperties
类中;
@ConfigurationProperties(prefix = "spring.thymeleaf")
public class ThymeleafProperties {
private static final Charset DEFAULT_ENCODING = StandardCharsets.UTF_8;
public static final String DEFAULT_PREFIX = "classpath:/templates/";
public static final String DEFAULT_SUFFIX = ".html";
//.....
2
3
4
5
6
7
也就是在 resources/templates 文件夹下放 HTML 文件;
# 新建 Controller
新建一个 Controller,用来跳转页面:
package com.peterjxl.boot.controller;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
@Controller
public class ViewTestController {
@GetMapping("/atguigu")
public String atguigu(Model model){
// model中的数据会被放在请求域中,相当于 request.setAttribute("msg", "hello, peterjxl!");
model.addAttribute("msg", "hello, peterjxl!");
model.addAttribute("link", "https://www.peterjxl.com");
// 会被视图解析器处理,相当于 return thymeleaf/success.html;
return "success";
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
# 新建 success.html
我们在 resources/templates 目录下,新建 success.html:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
</body>
</html>
2
3
4
5
6
7
8
9
10
然后我们添加 Thymeleaf 的名称空间(这样写 HTML 时就有提示,建议加上):
<html lang="en" xmlns:th="http://www.thymeleaf.org">
然后通过 Thymeleaf 的语法获取数据:
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<h1 th:text="${msg}">哈哈</h1>
<h2>
<a href="www.baidu.com" th:href="${link}">去百度</a>
</h2>
</body>
</html>
2
3
4
5
6
7
8
9
10
11
12
13
说明:
th:text
会替换掉标签里的文本数据,然后我们通过${}
的方式取出数据th:href
会替换掉 href 属性的值(要替换掉哪个属性的值,只需加上th:属性名
即可)
# 测试
我们访问 localhost: 8888/atguigu (opens new window):
# 源码
已将本文源码上传到 Gitee (opens new window) 或 GitHub (opens new window) 的分支 demo18,读者可以通过切换分支来查看本文的示例代码