在之前我们学习的都是 SpringBoot + Vue 或者 React 的前后端分离的项目,但是一些公司还是会使用一些混合模板开发的项目,甚至还要维护一些 Jsp 的老项目,其中就有 SpringBoot 官方推荐的模板引擎 Thymeleaf,通过在静态 HTML 嵌入标签属性,浏览器可以直接打开模板文件。以下为我在学习和实战练习过程中所做的笔记,可供参考。
一、Thymeleaf 基础使用
Thymeleaf 代码模版:
1 2 3 4 5 6 7 8 9 10
| <!doctype html> <html lang="en" xmlns:th="http://www.thymeleaf.org"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body>
</body> </html>
|
在 resources/templates/index.html
中写前端页面:
1 2 3 4 5 6
| <head> <meta charset="UTF-8" /> <title th:text="'Bezhuang'+${title}">默认的title</title> <meta th:content="${description}" name="description" content="默认的description"> <meta th:content="${keywords}" name="keywords" content="默认的keywords"> </head>
|
在 thymeleafdemo.controller/IndexController
中向前端页面传递参数:
1 2 3 4 5 6 7 8 9 10
| @Controller public class IndexController { @GetMapping("/index") public String index(Model model){ model.addAttribute("title", "传递的Index"); model.addAttribute("description", "传递的description"); model.addAttribute("keywords", "传递的keywords"); return "index"; } }
|
二、Thymeleaf 常用方法
在 resources/templates/basic.html
中写前端页面:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
| <body>
<h2 th:text="${user.username}"></h2> <p th:text="${user.age}"></p>
<div th:object="${user}"> <h2 th:text="*{username}"></h2> <p th:text="*{age}"></p> </div>
<p th:if="${user.isVip}">会员</p> <p th:if="${!user.isVip}">会员</p>
<ul> <li th:each="tag:${user.tags}" th:text="${tag}"></li> </ul>
<div th:switch="${user.sex}"> <p th:case="1">男</p> <p th:case="2">女</p> <p th:case="*">默认</p> </div> </body>
|
在 thymeleafdemo.controller/IndexController
中添加控制器:
1 2 3 4 5 6 7 8 9 10 11 12
| @GetMapping("/basic") public String basic(Model model){ UserVO userVO = new UserVO(); userVO.setUsername("Bezhuang"); userVO.setAge(24); userVO.setIsVip(true); userVO.setCreateTime(new Date()); userVO.setSex(1); userVO.setTags(Arrays.asList("Java", "JavaScript", "Python")); model.addAttribute("user", userVO); return "basic"; }
|
方法总结:
th:text
:文本的显示,其值会替换 HTML 中指定标签的值。
th:utext
:支持 HTML 的文本显示。
th:value
:给属性赋值。
th:object
:用于设置选定对条。
th:if
:条件判断,可以和 th:unless
配合使用。
th:switch
:选择判断,需要配合 th:case
使用。
th:each
:循环迭代。
th:href
: 设置链接地址。
th:src
:设置资源。
三、Thymeleaf 中 CSS、JS 的使用
引入 CSS 文件 app.css
:
1 2 3 4 5
| <head> <link rel="stylesheet" th:href="@{app.css}"> </head> <body> <div class="nav"></div>
|
引入 JavaScript:
1
| <script type="text/javascript" th:src="@{index.js}"></script>
|
动态引入 JavaScript,传入 user
参数:
1 2 3 4
| <script th:inline="javascript"> const printuser = {}; console.log(printuser); </script>
|
追加 CSS 样式:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| <head> <style> .nonactive { color: green; } .active { color: red; } </style> </head>
<div> <ol> <li th:each="tag,stat:${user.tags}" th:text="${tag}" th:classappend="${stat.last}?'active':nonactive" ></li> </ol> </div>
|
四、Thymeleaf 组件的使用
创建 fragment 碎片(组件):
1 2 3 4 5 6 7
| <footer th:fragment="com1"> com1 </footer>
<div id="com2"> com2 </div>
|
在 basic 页面中插入碎片:
1 2 3 4 5 6 7 8
| <div th:replace="~{component::com1}"></div>
<div th:insert="~{component::com1}"></div>
<div th:insert="~{component::#com2}"></div>
|
组件中使用外部对象:
1 2 3 4
| <footer th:fragment="com1"> <h2 th:text="${user}"></h2> </footer>
|
组件间传递参数:
1 2 3 4 5 6 7
| <div th:insert="~{component::com3('传递的参数')}"></div>
<div th:fragment="com3(message)"> <p th:text="${message}"></p> </div>
|
组件间传递模块:
1 2 3 4 5 6 7 8
| <div th:insert="~{component::com4(~{::#message})}"> <p id="message">传递的模块</p> </div>
<div th:fragment="com4(message)"> <div th:replace="${message}"></div> </div>
|
五、Thymeleaf 内置对象和工具类
内置对象
对象 |
描述 |
#ctx |
上下文对象 |
#vars |
同 #ctx,表示上下文变量 |
#locale |
上下文本地化(特定的地理区域)变量,可参考 java.util.Locale |
#request |
HttpServletRequest 对象,可参考 javax.servlet.http.HttpServletRequest |
#response |
HttpServletResponse 对象,可参考 javax.servlet.http.HttpServletResponse |
#session |
HttpSession 对象,可参考 javax.servlet.http.HttpSession |
#servletContext |
ServletContext 对象,可参考 javax.servlet.ServletContext |
#ctx
示例:
1 2 3 4 5 6
| <p th:text="${#ctx.getLocale()}"></p>
<p th:text="${#ctx.getVariable('message')}"></p>
<p th:text="${#ctx.containsVariable('message')}"></p>
|
#vars
示例:
1 2 3 4 5 6
| <p th:text="${#vars.getLocale()}"></p>
<p th:text="${#vars.getVariable('message')}"></p>
<p th:text="${#vars.containsVariable('message')}"></p>
|
#locale
示例:
1 2 3 4 5 6 7 8 9 10 11 12
| <p th:text="${#locale}"></p>
<p th:text="${#locale.country}"></p>
<p th:text="${#locale.displayCountry}"></p>
<p th:text="${#locale.language}"></p>
<p th:text="${#locale.displayLanguage}"></p>
<p th:text="${#locale.displayName}"></p>
|
#request
示例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| <p th:text="${#request.protocol}"></p>
<p th:text="${#request.scheme}"></p>
<p th:text="${#request.serverName}"></p>
<p th:text="${#request.serverPort}"></p>
<p th:text="${#request.method}"></p>
<p th:text="${#request.requestURI}"></p>
<p th:text="${#request.requestURL}"></p>
<p th:text="${#request.servletPath}"></p>
<p th:text="${#request.parameterNames}"></p>
<p th:text="${#request.parameterMap}"></p>
<p th:text="${#request.queryString}"></p>
|
注意,请求地址的 URL 参数直接通过#request.x
是取不出来的,需要使用param.x
语法来取出。如,URL:/standard-expression-syntax/variables?q=expression
,取出 q 参数的正确姿势:<p th:text="${param.q}"></p>
。
#response
示例:
1 2 3 4 5 6 7 8
| <p th:text="${#response.status}"></p>
<p th:text="${#response.bufferSize}"></p>
<p th:text="${#response.characterEncoding}"></p>
<p th:text="${#response.contentType}"></p>
|
#session
示例:
1 2 3 4 5 6
| <p th:text="${#session.id}"></p>
<p th:text="${#session.lastAccessedTime}"></p>
<p th:text="${#session.getAttribute('user').name}"></p>
|
注意,放到会话里面的对象直接通过#session.x
是取不出来的,需要使用session.x
语法来取出。如,取出会话里面的 user 对象的正确姿势:<p th:text="${session.user.name}"></p>
。
工具类
1 2 3 4 5
| <p th:text="${#strings.isEmpty(message)}"></p>
<p th:text="${#dates.format(now, 'yyyy-MM-dd HH:mm:ss')}"></p>
|