Java 开发可分为两种情况:前后端分离,适合于生命期长、迭代频繁的企业应用开发;后端不分离,则适合于短期的、演示性小项目,此时服务端可采用 Spring 官方推荐的模板 Thymeleaf。本文总结了 SpringBoot 整合 Thymeleaf 的开发要点。
作者:王克锋
出处:https://kefeng.wang/2018/03/23/spring-boot-thymeleaf/
版权:自由转载-非商用-非衍生-保持署名,转载请标明作者和出处。
1 概述
1.1 前端开发方案
根据静态页面和动态数据是否分离,分为两种方案:
- 前后端不分离:采用模板技术,服务端数据渲染至HTML模板,生成完整HTML页面返回给浏览器。流行的有 Thymeleaf、FreeMarker,早期的有 Velocity(Spring 官方已停止支持)、更早的是JSP(Spring 官方不建议)。
- 前后端分离:浏览器端刚开始只是静态页面,采用 ajax 请求获取数据,再通过 JS(或其封装) 渲染页面。潮流的开发框架有 Vue、React、AngularJS,传统的有 jQuery;
专业的开发推荐采用前后端分离方式,便于长久维护,比如 Vue;
演示性的、无需经常变更的小项目,可采用前后端不分离方式,开发工作量小,此时推荐使用 Thymeleaf。
所以,对于主要做前后端分离项目的同学,无需过深掌握 Thymeleaf。
1.2 Thymeleaf 概述
官网: https://www.thymeleaf.org/
Thymeleaf 是新一代 Java 模板引擎,Spring 官方推荐使用,也是 Spring Boot 默认的模板引擎。
模板语言见的用途有:
- 页面渲染
- 文档生成
- 代码生成
- 所有 “数据+模板=文本” 的应用场景
2 SpringBoot 项目整合
2.1 pom.xml
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
</dependencies>
2.2 resources/application.properties
spring.main.banner-mode=off
logging.level.org.springframework.web=WARN
logging.level.org.springframework.boot.web=WARN
logging.pattern.console=%d{HH:mm:ss.SSS} %p [%F:%L] - %m%n
## 开发过程中关闭缓存,上线时启用缓存
spring.thymeleaf.cache=false
spring.thymeleaf.prefix=classpath:/templates/
spring.thymeleaf.suffix=.html
2.3 准备静态文件
目录 resources/static 下创建三个目录: image(图片),script(脚本),style(样式)
新建样式文件 resources/static/style/main.css
h1 {
color: #0000FF;
}
h2 {
color: #FF0000;
}
2.4 resources/templates/welcome.html
<!DOCTYPE HTML>
<html xmlns:th="http://www.thymeleaf.org">
<!-- xmlns:th 引入 thymeleaf(缩写为 th) 命名空间,模板文件中的动态属性可以用 th:xxx 指定 -->
<head>
<title>Spring Boot + Thymeleaf demo</title>
<meta name="viewport" content="width=device-width, initial-scale=1" />
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
<link rel="stylesheet" th:href="@{/style/main.css}"/>
<!-- @{path} 引用 /static 下的静态资源文件 -->
</head>
<body>
<h1>Spring Boot + Thymeleaf demo</h1>
<h2 th:text="'Message: ' + ${message}"></h2>
<!-- ${xxx} 引用 SpringMVC 中 model 属性 -->
</body>
</html>
2.5 DemoApplication.java
@Controller
@SpringBootApplication
public class DemoApplication {
@RequestMapping("/")
public String welcome(Map<String, Object> model) {
model.put("message", "Hello World!");
return "welcome"; // templates\welcome.html
}
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
}
3 Thymeleaf 语法
官方文档:
https://www.thymeleaf.org/documentation.html
https://www.thymeleaf.org/doc/tutorials/2.1/usingthymeleaf.html
https://www.thymeleaf.org/doc/tutorials/3.0/usingthymeleaf.html
https://www.thymeleaf.org/doc/tutorials/2.1/usingthymeleaf.html#standard-expression-syntax
可根据所用的 SpringBoot 版本,选择相应的文档:
SpringBoot 版本 | Thymeleaf 版本 |
---|---|
1.5.13.RELEASE | 2.1.6.RELEASE |
2.0.2.RELEASE | 3.0.9.RELEASE |
3.1 DTD 声明
属性 xmlns:th 用来声明文档中的 th:xxx 属性是有效的。
HTML 会忽略 th:xxx 属性,但 Thymeleaf 模板引擎会把它翻译成 HTML 能够渲染的内容。
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:th="http://www.thymeleaf.org">
3.2 标准表达式语法
简单表达式:
- 变量表达式: ${…}
- 选择变量表达式: *{…}
- 消息表达式: #{…}
- 链接URL表达式: @{…}
字面
- 文本文字:’one text’,’Another one!’,…
- 号码文字:0,34,3.0,12.3,…
- 布尔文字:true,false
- 空文字: null
- 文字标记:one,sometext,main,…
文字操作:
- 字符串连接: +
- 文字替换: |The name is ${name}|
算术运算:
- 二元运算符:+,-,*,/,%
- 减号(一元运算符): -
布尔运算:
- 二元运营商:and,or
- 布尔否定(一元运算符): !,not
比较和平等:
- 比较:>,<,>=,<=(gt,lt,ge,le)
- 平等运营商:==,!=(eq,ne)
有条件的操作符:
- IF-THEN: (if) ? (then)
- IF-THEN-ELSE: (if) ? (then) : (else)
- 默认: (value) ?: (defaultvalue)
3.3 表达式对象
3.3.1 基本对象
- #ctx:上下文对象。
- #vars: 上下文变量。
- #locale:上下文语言环境。
- #httpServletRequest:(只在Web上下文中)HttpServletRequest对象。
- #httpSession:(只在Web上下文中)HttpSession对象。
3.3.2 工具对象
- #dates:java.util.Date对象的实用方法:格式化,组件提取等
- #calendars:类似于#dates,但对于java.util.Calendar物体。
- #numbers:用于格式化数字对象的实用方法。
- #strings:String对象的实用方法:contains,startsWith,prepending / appending等。
- #objects:一般对象的实用方法。
- #bools:布尔评估的实用方法。
- #arrays:数组的实用方法。
- #lists:列表的实用方法。
- #sets:集合的实用方法。
- #maps:地图的实用方法。
- #aggregates:用于在数组或集合上创建聚合的实用方法。
- #messages:用于在变量表达式中获得外部消息的实用方法,与使用#{…}语法获得的方式相同。
- #ids:用于处理可能会重复的id属性的实用方法(例如,作为迭代的结果)。
例子:
<span th:text="${#calendars.format(today,'dd MMMM yyyy')}">13 May 2011</span>
3.4 常用语法
3.4.1 变量
Java 中:model.put("message", "Hello World!");
HTML 中:<span th:text="${message}">Hello!</span>
3.4.2 message(外部化的文本)
默认的标准消息解析器: org.thymeleaf.messageresolver.StandardMessageResolver
文件中配置: application.properties 中指定 home.welcome=hello world!
模板中引用: <span th:text="#{home.welcome}"></span>
TODO: 试用尚未通过。
3.4.3 选择表达式
<div th:object="${session.user}">
<p>Name: <span th:text="*{firstName}">Sebastian</span>.</p>
<p>Surname: <span th:text="*{lastName}">Pepper</span>.</p>
<p>Nationality: <span th:text="*{nationality}">Saturn</span>.</p>
</div>
指定了 th:object"
,后面的 *{xxx}
限定在 ${session.user}
中。等价于:
<div>
<p>Name: <span th:text="${session.user.firstName}">Sebastian</span>.</p>
<p>Surname: <span th:text="${session.user.lastName}">Pepper</span>.</p>
<p>Nationality: <span th:text="${session.user.nationality}">Saturn</span>.</p>
</div>
3.4.5 条件
<div th:if="${user.isAdmin()} == false">
<div th:if="${variable.something} == null">
3.4.5 遍历
<tr th:each="user : ${users}">
<td th:text="${user.name}">john</td>
<td th:text="${user.sex}">male</td>
<td th:text="${user.ready}? #{true} : #{false}">yes</td>
</tr>
3.4.6 链接网址
<link rel="stylesheet" th:href="@{/style/main.css}"/>
<a href="main.html" th:href="@{/main}">
<form th:action="@{/createOrder}">
3.4.7 更多
https://www.thymeleaf.org/doc/tutorials/2.1/usingthymeleaf.html#conditional-evaluation