9 SpringBoot3【⑨ 模板引擎】
AI-摘要
切换
Tianli GPT
AI初始化中...
介绍自己
生成本文简介
推荐相关文章
前往主页
前往tianli博客
本文最后更新于 2023-09-22,文章内容可能已经过时。
9 SpringBoot3【⑨ 模板引擎】
- 由于 SpringBoot 使用了 嵌入式 Servlet 容器。所以 JSP 默认是 不能使用 的。
- 如果需要 服务端页面渲染,优先考虑使用
模板引擎
。
模板引擎
页面默认放在 src/main/resources/templates
SpringBoot 包含以下模板引擎的自动配置
● FreeMarker
● Groovy
● Thymeleaf
● Mustache
Thymeleaf官网
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<title>Good Thymes Virtual Grocery</title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<link rel="stylesheet" type="text/css" media="all" th:href="@{/css/gtvg.css}" />
</head>
<body>
<p th:text="#{home.welcome}">Welcome to our grocery store!</p>
</body
</html>
1. Thymeleaf整合
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
自动配置原理
- 开启了
org.springframework.boot.autoconfigure.thymeleaf.ThymeleafAutoConfiguration
自动配置 - 属性绑定在
ThymeleafProperties
中,对应配置文件spring.thymeleaf
内容 - 所有的模板页面默认在
classpath:/templates
文件夹下 - 默认效果
- 所有的模板页面在
classpath:/templates/
下面找 - 找后缀名为
.html
的页面
- 所有的模板页面在
- thymeleaf的配置在
spring.thymeleaf.xxxxxxxx
,一般不需要改前缀和后缀,建议开发期间使用spring.thymeleaf.cache=false
,开发期间关闭缓存,保证能随时改变随时看到效果 - 也可以修改
spring.thymeleaf.check-template=false
这样就不会检查是否存在对应的页面,可以增快软件加载速度。
2. 基础语法
1. 核心用法
th:xxx:动态渲染指定的 html 标签属性值、或者th指令(遍历、判断等)
th:text
:标签体内文本值渲染th:utext
:不会转义,显示为html原本的样子,如果文本带有html标签,可以直接渲染。
th:属性
:标签指定属性渲染th:attr
:标签任意属性渲染th:if
th:each
...
:其他th指令- 例如:
<p th:text="${content}">原内容</p>
<a th:href="${url}">登录</a>
<img src="../../images/gtvglogo.png"
th:attr="src=@{/images/gtvglogo.png},title=#{logo},alt=#{logo}" />
表达式:用来动态取值
${}
:变量取值;使用model共享给页面的值都直接用${}@{}
:url路径;防止根目录变化,可以在配置文件通过server.servlet.context-path
改变#{}
:国际化消息~{}
:片段引用*{}
:变量选择:需要配合th:object绑定对象
系统工具&内置对象:详细文档
param
:请求参数对象session
:session对象application
:application对象#execInfo
:模板执行信息#messages
:国际化消息#uris
:uri/url工具#conversions
:类型转换工具#dates
:日期工具,是java.util.Date
对象的工具类#calendars
:类似#dates,只不过是java.util.Calendar
对象的工具类#temporals
: JDK8+java.time
API 工具类#numbers
:数字操作工具#strings
:字符串操作#objects
:对象操作#bools
:bool操作#arrays
:array工具#lists
:list工具#sets
:set工具#maps
:map工具#aggregates
:集合聚合工具(sum、avg)#ids
:id生成工具
2. 语法示例
表达式:
- 变量取值:
${...}
- url 取值:
@{...}
- 国际化消息:
#{...}
- 变量选择:
*{...}
- 片段引用:
~{...}
常见:
- 文本:
'one text'
,'another one!'
,… - 数字:
0
,34
,3.0
,12.3
,… - 布尔:
true
、false
- null:
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)
- default:
(value)?:(defaultValue)
特殊语法:
- 无操作:
_
所有以上都可以嵌套组合
'User is of type ' + (${user.isAdmin()} ? 'Administrator' : (${user.type} ?: 'Unknown'))
3. 属性设置
th:href="@{/product/list}"
th:attr="class=${active}"
th:attr="src=@{/images/gtvglogo.png},title=${logo},alt=#{logo}"
th:checked="${user.active}"
<p th:text="${content}">原内容</p>
<a th:href="${url}">登录</a>
<img src="../../images/gtvglogo.png"
th:attr="src=@{/images/gtvglogo.png},title=#{logo},alt=#{logo}" />
4. 遍历
语法: th:each=“元素名,迭代状态 : ${集合}”
<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>
<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>
iterStat
有以下属性:
index
:当前遍历元素的索引,从0开始count
:当前遍历元素的索引,从1开始size
:需要遍历元素的总数量current
:当前正在遍历的元素对象even/odd
:是否偶数/奇数行first
:是否第一个元素last
:是否最后一个元素
5. 判断
th:if
<a
href="comments.html"
th:href="@{/product/comments(prodId=${prod.id})}"
th:if="${not #lists.isEmpty(prod.comments)}"
>view</a>
th:switch
<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>
6. 属性优先级
- 片段
- 遍历
- 判断
<ul>
<li th:each="item : ${items}" th:text="${item.description}">Item description here...</li>
</ul>
Order | Feature | Attributes |
---|---|---|
1 | 片段包含 | th:insert th:replace |
2 | 遍历 | th:each |
3 | 判断 | th:if th:unless th:switch th:case |
4 | 定义本地变量 | th:object th:with |
5 | 通用方式属性修改 | th:attr th:attrprepend th:attrappend |
6 | 指定属性修改 | th:value th:href th:src ... |
7 | 文本值 | th:text th:utext |
8 | 片段指定 | th:fragment |
9 | 片段移除 | th:remove |
7. 行内写法
[[...]]
or [(...)]
<p>Hello, [[${session.user.name}]]!</p>
8. 变量选择
<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>
等同于
<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>
9. 模板布局
像页面导航等这种通用的部分,可以直接放到一个common.html页面,然后我们给它定义模板片段,然后在别的页面引用。
如在common.html 定义一个header
<header th:fragment="myheader" .....></header>
在别的页面就能引用或者插入它
<div th:replace="~{common :: myheader}"></div>
- 定义模板:
th:fragment
- 引用模板:
~{templatename::selector}
- 插入模板:
th:insert、th:replace
<footer th:fragment="copy">© 2011 The Good Thymes Virtual Grocery</footer>
<body>
<div th:insert="~{footer :: copy}"></div>
<div th:replace="~{footer :: copy}"></div>
</body>
<body>
结果:
<body>
<div>
<footer>© 2011 The Good Thymes Virtual Grocery</footer>
</div>
<footer>© 2011 The Good Thymes Virtual Grocery</footer>
</body>
</body>
th:insert
:保留自己的主标签,保留th:fragment的主标签。th:replace
:不要自己的主标签,保留th:fragment的主标签。th:include
:保留自己的主标签,不要th:fragment的主标签。(官方3.0后不推荐)
需要替换的片段内容:
<footer th:fragment="copy">
<script type="text/javascript" th:src="@{/plugins/jquery/jquery-3.0.2.js}"></script>
</footer>
导入片段:
<div th:insert="footer :: copy"></div>
<div th:replace="footer :: copy"></div>
<div th:include="footer :: copy"></div>
结果为:
<div>
<footer>
<script type="text/javascript" th:src="@{/plugins/jquery/jquery-3.0.2.js}"></script>
</footer>
</div>
<footer>
<script type="text/javascript" th:src="@{/plugins/jquery/jquery-3.0.2.js}"></script>
</footer>
<div>
<script type="text/javascript" th:src="@{/plugins/jquery/jquery-3.0.2.js}"></script>
</div>
10. devtools
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
</dependency>
修改页面后;ctrl+F9
刷新效果;
java代码的修改,如果devtools
热启动了,可能会引起一些bug,难以排查
所以如果使用devtools,修改Java代码最好重新启动,不要使用 ctrl + F9 ,前端页面修改可以使用
- 感谢你赐予我前进的力量
赞赏者名单
因为你们的支持让我意识到写文章的价值🙏
本文是原创文章,采用CC BY-NC-ND 4.0协议,完整转载请注明来自FanXYの秘密基地
评论
匿名评论
隐私政策
你无需删除空行,直接评论以获取最佳展示效果