模板:页面静态化技术->html(Idea改了html可以点击工具栏重构项目不需要重启)
Thymeleaf 是个什么?
简单说, Thymeleaf 是一个跟 Velocity、FreeMarker 类似的模板引擎,它可以完全替代 JSP 。相较与其他的模板引擎,它有如下三个极吸引人的特点:
1.Thymeleaf 在有网络和无网络的环境下皆可运行,即它可以让美工在浏览器查看页面的静态效果,也可以让程序员在服务器查看带数据的动态页面效果。这是由于它支持 html 原型,然后在 html 标签里增加额外的属性来达到模板+数据的展示方式。浏览器解释 html 时会忽略未定义的标签属性,所以 thymeleaf 的模板可以静态地运行;当有数据返回到页面时,Thymeleaf 会动态地替换掉静态内容,使页面动态显示。
2.Thymeleaf 开箱即用的特性。它提供标准和spring标准两种方言,可以直接套用模板实现JSTL、 OGNL表达式效果,避免每天套模板、改jstl、改标签的困扰。同时开发人员也可以扩展和创建自定义的方言。
-
Thymeleaf 提供spring标准方言和一个与 SpringMVC 完美集成的可选模块,可以快速的实现表单绑定、属性编辑器、国际化等功能。
一、导包:
<!-- 引入thymeleaf模版 --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-thymeleaf</artifactId> </dependency>
二、Eclipse插件(IDEA不用安装):
Thymeleaf Eclipse Plugin Update Site 或者直接在市场搜索安装 然后项目右键->Thymeleaf->Add thymeleaf...
html:
<html xmlns:th="http://www.thymeleaf.org">
三、yml配置:(可以不配全部采用默认值)
spring: thymeleaf: encoding: UTF-8 #开发时关闭缓存(模板只加载一次),不然没法看到实时页面需要重构或重启 cache: false mode: HTML5 (默认) prefix: classpath:/templates/ (默认) suffix: .html (默认)
四、代码:
-
后台Controller
@GetMapping("/message") public String getMessage(Model model){ model.addAttribute("message","This is your message"); return "index"; }
-
页面通过Model取值
<p th:text="${message}">default message</p>
-
js通过model取值
<script th:inline="javascript"> var message = [[${message}]]; console.log(message); </script>
注:script标签中 th:inline 一定不能少
js中免不了的要用的数组,一维的二维的三维的,但是当用到thymeleaf作为模版时候会有一些坑,导致数组不能用
var cols=[[{field:'checkBox',checkbox: true},{field:'username', title: '用户名'}]];
解决: 方法一:回车换行如下:
var cols=[ [ {field:'checkBox',checkbox: true},{field:'username', title: '用户名'} ] ];
方法二:添加th:inline="javascript",默认是th:inline="text"
-
简单表达式 (simple expressions)
${...}
变量表达式*{...}
选择变量表达式#{...}
内置对象@{...}
链接url|src|action|href表达式 (可以直接定位项目根目录 href="@{/css/main.css}")
五、常用thymeleaf标签属性:
-
th:text="${data}",将data的值替换该属性所在标签的body。字符常量要用引号,比如th:text="'hello world'",th:text="2011+3",th:text="'my name is '+${user.name}"
-
th:utext,和th:text的区别是"unescaped text"。<c:out value="<a></a>"/>
-
th:with,定义变量,th:with="${count}*100/${total}+'%'",定义多个变量可以用逗号分隔。
-
th:attr,设置标签属性,多个属性可以用逗号分隔,比如th:attr="src=@{/image/aa.jpg},title=#{logo}",此标签不太优雅,一般用的比较少。
-
th:[tagAttr],设置标签的各个属性,比如th:value,th:action,th:src等。 可以一次设置两个属性,比如:th:alt-title="${logo}" 对属性增加前缀和后缀,用th:attrappend,th:attrprepend,
比如:th:attrappend="class=${' '+cssStyle}" 对于属性是有些特定值的,比如checked属性,thymeleaf都采用bool值,
比如th:checked=${user.isActive}
-
th:each, 循环,
<tr th:each="user,userStat :${users}">
,userStat是状态变量,有 index,count,size,current,even,odd,first,last等属性,如果没有显示设置状态变量,thymeleaf会默认给个“变量名+Stat"的状态变量。 -
th:if or th:unless,条件判断,支持布尔值,数字(非零为true),字符,字符串。
-
th:switch,th:case,选择语句。 th:case="*"表示default case。
-
th:placeholder="#{login.userName}"国际化标签(spring.messages.basename=i18n.login)
-
th:include 能渲染包含的模板页 iframe不会渲染,直接显示静态html
<div th:include="model/mymodel.html"></div> <iframe src="model/mymodel.html"></iframe>
<!-- 回显 th:field不能用于${session.ch} *{session.ch.id}--> <select th:field="*{category.id}"> <option th:each="choice : ${allCategories}" th:value="${choice.id}" th:selected="(${choice.id == category.id})" th:text="${choice.description}"></option> </select> <form action="#" th:object="${user}"> 编号:<input th:value="*{id}"/> 用户名:<input th:value="*{username}"/> </form>
循环取map的值:
<table> <tr th:each="m:${map}"> <td th:text="${m.key}"></td> <td th:text="${m.value}"></td> </tr> </table>
根据键变量取map的值:
<ul> <li th:each="k: ${list}" > //${map.k} <option th:each="v:${map.get(k)}">...</option> </li> </ul> <!-- 或者 --> ${map[__${k}__]} //${map[k]}
六、内置对象:
dates:java.util.Date的功能方法类
calendars:类似#dates,面向java.util.Calendar
temporals:类似#dates,面向LocalDate、LocalDateTime
numbers:格式化数字的功能方法类
strings:字符串对象的功能类,contains,startWiths,prepending/appending等等
objects:对objects的功能类操作
bools:对布尔值求值的功能方法
arrays:对数组的功能类方法
lists:对list集合功能类方法
sets:对set集合功能类方法
maps:对map集合功能类方法
aggregates:对数组或者集合创建聚合的功能方法${#aggregates.avg(array)}
messages:在变量表达式中获取外部信息的功能类方法。
ids:处理可能重复的id属性的功能类方法。
如:
<dd th:text="${#numbers.formatDecimal(product.price, 1, 2)}">180</dd> <dd th:text="${#dates.format(product.availableFrom, 'yyyy-MM-dd')}">2014-12-01</dd> <dd th:text= "${#aggregates.sum(o.orderLines.{purchasePrice*amount})}">1</dd>
七、URL参数:
绝对路径:th:href="@{http://www.baidu.com}" == href='http://www.baidu.com' 相对路径:相对于项目的根th:href="@{/details/}"(注意前面用/
开头)
(orderId=${o.id},name=${name}) 相当于 ?orderId=${o.id}&name=${name}(因为'?'当三元表达式解析)
<a th:href= "@{'/details/'+${user.login}(orderId=${o.id},name=${name})}"></a> <a th:href= "@{'/page'(pageIndex=${pageIndex},pageSize=${pageIndex})}">page</a>
restful:/
必须使用'/'
拼接,否则将做除法运算
<a th:href="@{'/details/'+${user.login}/${user.password}}"></a> <!-- 两个数字 --> <a th:href="@{'/page/'+${pageIndex}+'/'+${pageSize}}"></a>
src:
<img src="../images/qr-code.jpg" th:src="@{${path}}" alt="" />
action:(th:object="${new}"不能取值)
<form th:action="@{'/admin/'+${path}}" th:object="${user}" method="post"> <input type="text" th:value="*{name}"/> <input type="text" th:value="*{msg}"/> <input type="submit"/> </form>
八、根据模板静态化页面
引入ognl依赖:
<!-- thymeleaf模板生成需要 --> <dependency> <groupId>ognl</groupId> <artifactId>ognl</artifactId> <!-- 新版ognl在springboot2.5+以上少包 --> <!-- <version>3.3.4</version> --> <version>3.2.1</version> </dependency>
工具类:
/** * 模板工具类 */ public class ThymeleafUtils { /** * 创建出一个name.html文件 * @param templateName 模板名称 * @param name 生成name.html * @param map 模板映射参数 */ public static void createHtml(String templateName, String name, Map<String, Object> map) { PrintWriter writer = null; try { // 1. 创建模板解析器 并设置相关属性 ClassLoaderTemplateResolver resolver = new ClassLoaderTemplateResolver(); // 配置解析器模板存储文件夹路径 resolver.setPrefix("/templates/model/"); // 配置解析器模板文件后缀 resolver.setSuffix(".html"); TemplateEngine templateEngine = new TemplateEngine(); templateEngine.setTemplateResolver(resolver); // 2. 模板上下文 主要存储Model参数 Context context = new Context(); context.setVariables(map); // 3. 创建输出文件 File folder = new File("demo/src/main/resources/static/html"); //如果目录不存在,直接创建 if (!folder.exists()) { folder.mkdir(); } folder = new File("demo/src/main/resources/static/html", name + ".html"); // 5. 获取输出目标文件输出流 writer = new PrintWriter(folder, "UTF-8"); // 6. 生成静态模板参数1:template模板名称 参数2:上下文对象 参数3:目标文件输出流 templateEngine.process(templateName, context, writer); } catch (IOException e) { e.printStackTrace(); } finally { // flush输出流并关闭 if (writer != null) { writer.flush(); writer.close(); } } } public static void main(String[] args) { Map<String, Object> map = new HashMap<>(); map.put("keywords","HUAWEIMateBook D,华为MateBook D,华为MateBook D报价,HUAWEIMateBook D报价"); map.put("content","京东JD.COM提供华为MateBook D正品行货,并包括HUAWEIMateBook D网购指南,以及华为MateBook D图片、MateBook D参数、MateBook D评论、MateBook D心得"); map.put("name","鬼子列表"); map.put("array",new String[]{"安倍", "张洋", "洋鬼子", "万琪小次郎"}); ThymeleafUtils.createHtml("goods","result",map); } }
<!-- goods.html模板 --> <!DOCTYPE html> <html lang="en" xmlns:th="http://www.thymeleaf.org"> <head> <meta charset="UTF-8"> <meta name="keywords" th:content="${keywords}" content=""/> <meta name="description" th:content="${content}" content="" /> <meta name="format-detection" content="telephone=no"> <title>Title</title> </head> <body> <h1 th:text="${name}">列表名称</h1> <ul> <li th:each="item: ${array}" th:text="${item}">条目</li> </ul> </body> </html>