一 模板引擎
模板引擎是一种技术工具,主要用于使用户界面与业务数据(内容)实现分离。通过模板引擎,开发者可以生成特定格式的文档,例如在Web开发中,它可以生成标准的HTML文档。模板引擎的应用并不局限于特定的技术领域,而是跨领域、跨平台的概念,这意味着在多种编程语言和开发环境中,如Asp、PHP、C#、JavaScript以及WinForm开发等,都可以看到模板引擎的应用。
模板引擎的工作原理基于模板语言,通过该语言,页面被制成模板。之后,根据业务逻辑,模板引擎将这些模板语言翻译成业务数据,从而生成最终展示页面。这样,不仅实现了代码分离(业务逻辑代码和用户界面代码),也实现了数据分离(动态数据与静态数据),提升了开发效率。
模板引擎有多种类型,根据实现方式的不同,可以大致分为置换型、解释型和编译型。置换型模板引擎相对简单,它仅将模板内容中的特定标记替换为业务数据。然而,这种方式的效率较低,可能无法满足高负载应用的需求。因此,解释型和编译型模板引擎应运而生,它们具有更高的效率,能更好地处理复杂的应用场景。
在Web开发中,模板引擎的应用非常广泛,常见的模板引擎包括jsp、freemarker、velocity等。这些模板引擎都有自己的语法和特点,可以帮助开发者更高效地生成和展示页面内容。例如,jsp功能强大,支持标签和表达式语言,具有官方标准和良好的性能表现;而freemarker和velocity则以其简洁和易用的语法受到开发者的青睐。
总的来说,模板引擎是Web开发和其他领域中的重要工具,它通过实现数据和代码的分离,大大提高了开发效率和代码的可维护性。
二 Thymeleaf 简介
Thymeleaf是适用于 Web 和独立环境的现代服务器端 Java 模板引擎。在Spring 官方支持模板引擎中,并不包含 JSP,而是 Thymeleaf 和 FreeMarker 等,Thymeleaf 与 Spring Boot 的自动化配置集成适配度很高,几乎没有任何成本,只关注 Thymeleaf 的语法即可。
Thymeleaf的原理就是:模板 + 数据模型 = 输出,模板只负责数据在页面中的表现,不涉及任何的逻辑代码,而所有的逻辑都是由数据模型来处理的。用户最终看到的输出是模板和数据模型合并后创建的。
Thymeleaf 特点:
① 动静结合:Thymeleaf支持在HTML标签中添加额外的属性来实现模板与数据的结合。这种设计使得开发者可以在静态环境下预览模板效果,同时在动态环境下展示数据。
② 与Spring Boot完美整合:Spring Boot为Thymeleaf提供了默认配置和视图解析器,使得在Spring Boot项目中使用Thymeleaf变得非常简单。开发者可以像操作JSP一样操作Thymeleaf,只需关注模板语法即可。
③ 清晰的分工:Thymeleaf专注于页面表现,而将业务逻辑留给数据模型处理。这种分工使得页面内容更加清晰、可读性强,降低了后期的维护难度。
④ 高效的渲染:JSP 在第一次执行的时候需要转换成 Servlet 类,之后的每次修改都要编译和转换。这样就造成了每次修改都需要等待编译的时间,开发效率低下。Thymeleaf 避免了这些额外的开销,从而提高了渲染视图的效率。
⑤ 内存优势:JSP 编译后要把字节码加载到 JVM 的内存中,如果页面多了容易导致内存溢出问题,但是 Thymeleaf 则不会一直占着内存,用完后被清理,有效避免了内存溢出的问题。
三 Thymeleaf 入门
1 导入依赖
<dependency>
<groupId>org.thymeleaf</groupId>
<artifactId>thymeleaf-spring5</artifactId>
<version>3.0.12.RELEASE</version>
</dependency>
2 配置视图解析器
<!--视图解析器 springboot内部集成可不进行配置直接使用-->
<bean id="templateResolver" class="org.thymeleaf.spring5.templateresolver.SpringResourceTemplateResolver">
<property name="prefix" value="/WEB-INF/views/" /><!--前缀-->
<property name="suffix" value=".html" /><!--后缀-->
<property name="templateMode" value="HTML" /><!--模板引擎的格式-->
<property name="cacheable" value="false" /><!--是否缓存-->
</bean>
<!--模板引擎关联视图解析器-->
<bean id="templateEngine" class="org.thymeleaf.spring5.SpringTemplateEngine">
<property name="templateResolver" ref="templateResolver" />
</bean>
<!--调用模板引擎生成html文档-->
<bean class="org.thymeleaf.spring5.view.ThymeleafViewResolver">
<property name="templateEngine" ref="templateEngine" />
<!--页面中显示的编码格式-->
<property name="characterEncoding" value="UTF-8" />
</bean>
3 编写 html 模板文件
Thymeleaf 中所有的表达式都需要写在"指令"中,指令是 HTML5 中的自定义属性,在 Thymeleaf 中所有指令都是以 th:
开头。因为表达式 ${msg}
是写在自定义属性中,因此在静态环境下,表达式的内容会被当做是普通字符串,浏览器会自动忽略这些指令,这样就不会报错了。
<!DOCTYPE html>
<!--thymeleaf约束引入-->
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>入门示例</title>
</head>
<body>
<!--thymeleaf标签使用-->
<p th:text="${msg}"></p>
</body>
</html>
四 Thymeleaf 使用
1 Thymeleaf 内置对象
环境相关对象 | 作用 |
---|---|
ctx | 获取 Thymeleaf 自己的 Context 对象 |
requset | 若是 Web 程序,可以获取 HttpServletRequest 对象 |
response | 若是 Web 程序,可以获取 HttpServletReponse 对象 |
session | 若是 Web 程序,可以获取 HttpSession 对象 |
servletContext | 若是 Web 程序,可以获取 HttpServletContext 对象 |
Thymeleaf 提供的全局对象 | 作用 |
---|---|
#dates | 处理 java.util.Date 的工具对象 |
#calendars | 处理 java.util.Calendar 的工具对象 |
#numbers | 用来对数字格式化的方法 |
#strings | 用来处理字符串的方法 |
#bools | 用来判断布尔值的方法 |
#arrays | 用来护理数组的方法 |
#lists | 用来处理 List 集合的方法 |
#sets | 用来处理 set 集合的方法 |
#maps | 用来处理 map 集合的方法 |
<p>
today: <span th:text="${#dates.format(today,'yyyy-MM-dd')}">2024-03-20</span>
</p>
2 字面值
于在指令中填写基本类型如:字符串、数值、布尔等,且不希望被 Thymeleaf 解析为变量,称为字面值。
<!DOCTYPE html>
<!--thymeleaf约束引入-->
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>入门示例</title>
</head>
<body>
<!--字符串字面值-->
<!--使用一对 ' 引用的内容就是字符串字面值-->
<!--`th:text` 中的 Thymeleaf 并不会被认为是变量,而是一个字符串-->
<p>
你正在观看 <span th:text="'thymeleaf'">template</span> 的字符串常量值。
</p>
<!--普通字符串与表达式拼接-->
<span th:text="'欢迎您:' + ${name} + '!'"></span>
<!--字符串字面值需要用 `''`,拼接起来非常麻烦,Thymeleaf 对此进行了简化,使用一对 `|` 即可-->
<span th:text="|欢迎您:${name}|"></span>
<!--数字字面值 无特殊语法 可直接进行算术运算-->
<p>今年是 <span th:text="2021">1970</span></p>
<p>十年后将会是 <span th:text="2021 + 10">1980</span></p>
<!--布尔类型的字面值是 true 或 false-->
</body>
</html>
3 运算
${}
内部的是通过 OGNL 表达式引擎解析的,外部的才是通过 Thymeleaf 的引擎解析,因此运算符尽量放在 ${}
外进行。
① 算术运算:支持的算术运算符:+
、-
、*
、/
、%
。
<span th:text="${student.age}"></span>
<span th:text="${student.age}%3 == 0"></span>
② 比较运算:支持的比较运算:>
,<
,>=
,<=
,==
,!=
,and
,or
,但是 >
,<
不能直接使用,因为 XML 会解析为标签,要使用别名。 ==
和 !=
不仅可以比较数值,类似于 equals 的功能。
可以使用的别名:
gt(>)
lt(<)
ge(>=)
le(<=)
not(!)
eq(==)
neq/ne(!=)
③ 条件运算:有的时候需要设置默认值,我们取一个值可能为空,这个时候需要做非空判断,可以使用表达式 ?:
默认值简写(?:
之间没有空格):
<span th:text="${student.gender} ? '男':'女'"></span>
<!--当前面的表达式值为 null 时,就会使用后面的默认值-->
<span th:text="${student.name} ?: 'lony'"></span>
4 判断
使用 th:if
或者 th:unless
,二者意思相反
<span th:if="${age} > 18">年龄大于 18</span>
上面如果表达式的值为 true,则标签会渲染到页面,否则不进行渲染。以下情况被认定为 true:
1.表达式值为 true
2.表达式值为非 0 数值
3.表达式值为非 0 字符
4.表达式值为字符串,但不是 false,no,off
5.表达式不是布尔、字符串、数字、字符中的任何一种
6.其它情况包括 null 都被认定为 false
分支控制 switch 指令:th:switch
和 th:case
。一旦有一个 th:case
成立,其它的则不再判断。与 Java 中的 switch 是一样的。另外 th:case="*"
表示默认,放最后。
<div th:switch="${student.role}">
<p th:case="'admin'">学生班长</p>
<p th:case="'manager'">学生副班长</p>
<p th:case="*">其它角色学生</p>
</div>
5 循环
<tr th:each="employee,stat:${employees}">
<td th:text="${stat.count}">1</td>
<td th:text="${student.id}">1</td>
<td th:text="${student.name}">坤坤</td>
<td th:text="${student.password}">666</td>
</tr>
其中 stat 对象包含以下属性:
index,从 0 开始的角标
count,元素的个数,从 1 开始
size,总元素个数
current,当前遍历到的元素
even/odd,返回是否为奇偶,boolean 值
first/last,返回是否为第一或最后,boolean 值
6 JS 模板
模板引擎不仅可以渲染 HTML,也可以对 JS 中的进行预处理。而且为了在纯静态环境下可以运行,其 Thymeleaf 代码可以被注释起来。
1.首先在 script 标签中通过 th:inline="javascript" 来声明这是要特殊处理的 JS 脚本。
2.其次使用如下语法结构:
var 变量名 = /*[[Thymeleaf表达式]]*/ 静态环境下的默认值;
<script th:inline="javascript">
var Studentname = /*[[${username}]]*/ 'lili';
var age = /*[[${age}]]*/ 20;
console.log(username);
console.log(age)
</script>
7 fragment 方式
在 Thymeleaf 模板中有个指令实现 fragment 方式
th:insert:把整个 fragment 插入到当前节点内部。
th:replace:用 fragment 替换到当前节点。
th:include:把 fragment 的内容(不包括 fragment 的节点)插入到当前节点。
被引入模板文件 hello.html,内容如下
<span th:fragment="cptxt">
这里是wbl广场
</span>
引入上面模板的文件 home.html,内容如下:
<div th:replace="hello:: cptxt"></div>
<div th:insert="hello:: cptxt"></div>
<div th:include="hello:: cptxt"></div>
两模板文件在同一目录下。