前言:Thymeleaf是新一代Java模板引擎,基于自然模板的理念让其既适合原型设计,又适合开发测试,同时,对于广大JSP程序员来说,上手非常容易。但是,很多新程序员还是存在一些学习障碍。本文结合SpringBoot和Gradle来逐步介绍Thymeleaf关键知识点,只要一天就能真正入门。
1.按部就班开发大表查询应用程序
下面给出一个实例来巩固相关知识。我们的实例使用STS 4.17(IDEA下类似)。
1.1新建Spring Boot项目
使用Spring Starter Project向导来新建源代码工程项目:
1.2检查配置文件build.gradle
Spring Starter Project默认创建了build.gradle,里面引用了四个组件:Spring Web,Spring Configuration Processor,Thymeleaf,Lombok,如下:
1.3前端页面
1.3.1新增html文件:index.html
在resource/templates/thymeleaf下面新增html文件:index.html
- @{}变量表达式用于获取当前上下文路径。
- /thymeleaf, /smalllist.thymeleaf, /biglist.thymeleaf要在后台控制器中定义。
- /images/TH属性介绍1.png,/images/TH属性介绍2.png,/images/TH属性介绍3.png,/images/thymeleaf_logo.png都是静态图片存放在images目录中。
- ${#dates.createNow()}引用了dates函数包中的函数createNow()。
1.3.2新增html文件:smalllist.html
其中,
- <meta http-equiv="Content-Type" cnotallow="text/html; charset=UTF-8" />定义了文档类型和编码方式。
-
<style type="text/css">定义了样式:table{border-collapse:collapse;border-spacing:1px; width:100%; border:#000 solid 1px;}定义了table标签的样式,
table td{border:1px solid #000;height:25px; text-align:left; border-left:1px;}定义了table内部td标签的样式,
table th{text-align:left; background:#edd3d4; color:#a10333; border:#000 solid 1px; white-space:nowrap; height:21px; border-top:1px;border-left:1px;}定义了table内部th标签的样式。
table定义表格,其中th定义表格标题行,td定义表格内容单元格。
border-collapse:collapse指table的border与cellspacing属性没有作用,th和td的border与cellspacing属性有作用。
border-spacing:1px指边框线之间间距1像素,不管是水平还是垂直。
width:100%:指使用父元素的100%宽度。
text-align是文本对齐方式,left指左对齐。
background指背景颜色。
color指文字颜色。
border:#000 solid 1px指边框颜色为黑色,边框采用实心线,宽度为1像素(px),这是一种顺序设置方法,冒号后面可以随意更换顺序。
white-space:nowrap指强制不换行。
height高度,px表示像素。
border-top:1px顶部边框宽1像素。
border-left左边边框宽1像素。 - <tr th:each="e : ${entries}">使用了Thymeleaf属性标签th:each, ${entries}是选择表达式,用于选中对象entries,这个对象是后台返回来的。th:each和${entries}作用后表示从后台返回的列表对象entries获取每个元素存放到e这个变量中。
- <td th:text="${e.deviceId}">...</td>使用了Thymeleaf属性标签th:text,获取e.deviceId值来替换原来的td标签限定的内容,即...
1.3.3新增html文件:biglist.html
这个文件和smalllist.html类似,区别在于后台返回的对象是dataSource。
1.4新增后台类
1.4.1新增model类Device
在STS的new菜单下点class,出现下图:
新增属性和注解,如下:
1.4.2新增控制器
在new菜单下点class:
在控制器中新增方法和注解,如下:
1.4.3新增JPA仓库类
在new下点interface:
新增方法,如下:
其中,DeviceRepository 继承了JpaRepository。
JpaRepository归属于Spring Data JPA组件,JpaRepository在Spring Data体系的位置如下图所示:
说明继承关系的类图如下:
JpaRepository的主要方法如下:
我们在DeviceRepository里面只提供了findAll()方法,该方法用于查询所有记录。
1.4.4启动和测试
在Boot Dashboard中启动应用:
在浏览器中输入地址:
点小列表,如下:
1.5源代码分享
GITEE地址:
https://gitee.com/radarfyh/thymeleaf-jpa-mysql-biglist.git
2.Gradle配置使用
Gradle新一代的源代码工程(项目)自动化构建工具,用于代替Apache Ant和Apache Maven。它使用一种基于Groovy的特定领域语言(DSL)来声明源代码工程设置,也增加了基于Kotlin语言的kotlin-based DSL,抛弃了基于XML的各种繁琐配置。目前非常流行于安卓APP开发和java后台开发。
2.1下载安装
进入下载链接https://services.gradle.org/distributions/
如下:
选择gradle-7.6-bin.zip,解压到D:\gradle\gradle-7.6
对于windows 10操作系统,打开“编辑系统环境变量”:
进入“环境变量”,新增:
GRADLE_HOME= D:\gradle\gradle-7.6
再修改Path增加%GRADLE_HOME%\bin
使用gradle –v验证版本:
可以通过环境变量指定本地仓库:
GRADLE_USER_HOME=f:\maven-repository
2.2配置和启动
(1)远程仓库配置
全局远程仓库配置:在文件夹D:\gradle\gradle-7.6\init.d中新建文件init.gradle,填充以下内容:
(2)代码工程(项目)仓库配置
build.gradle文件是配置项目中要使用的gradle库文件,和Maven工程中的pom.xml相同。
可添加本项目的仓库配置:
下面描述POM和build.gradle的映射方法。假设pom.xml中的依赖:
build.gradle中的依赖:
更新build.gradle:项目右键,点Gradle-->Refresh Gradle Project。
然后,增加一句:api 'org.apache.commons:commons-lang3:3.8.1'
重新更新build.gradle后自动下载,如下图:
完成后增加一个类CheckNum来试试包依赖是否成功加入,如下图:
运行后,如下图:
项目中依赖库也会显示出来:
刷新项目时先检查本地仓库是否存在依赖包,不存在这从互联网上的远程库中下载到本地仓库。
本地仓库默认路径为:C:\users\用户名\.gradle。
Commons-lang3的本地库路径为:
C:\Users\Administrator\.gradle\caches\modules-2\files-2.1\org.apache.commons\commons-lang3\3.8.1
修改本地库路径,项目右键Properties-->Gradle-->Gradle User Home:
在互联网仓库中查看commons-lang3,地址为:
https://mvnrepository.com/artifact/org.apache.commons/commons-lang3
在eclipse-->new-->project…中新建一个demo项目,如下:
下一步显示关于集成的说明,再下一步如下:
点下一步,可以选择覆盖工作区设置,提供自己安装的gradle发布版,可以指定其本地安装路径,如下:
点configure workspace settings…显示各项目通用的工作区的gradle设置界面:
如果在specific gradle version选择的gradle版本没有安装,eclipse会自动安装,但是由于国外网站,可能会导致下载速度很慢,所以,先前在init.gradle文件中做了一些国外不稳定的地址链接的替换。
最后显示preview,如下:
目录结构如下:
- src/main/java文件夹,包含所有java源文件。
- src/test/java文件夹,包含所有java测试用例。
- build.gradle文件,包含项目构建所使用的脚本。
- settings.gradle文件,包含任务或项目之间的依懒关系等。
- gradle : gradle的jar包与配置文件
- gradlew : gradle的跨平台执行文件
2.3 Gradle、Maven和Ant对比
最初使用make工具,2000年基于make工具改进而来的ant出来,过程式,后来支持插件,采用XML作为脚本编写格式。为了简化越来越大的XML配置文件,使用Apache Ivy管理依赖。
Maven发布于2004年,解决Ant的问题,不再使用任务的概念,而是使用目标goal,并具有自动从网络下载依赖的能力。缺点是不适合大型项目,XML文件比ant还要庞大。
Gradle在2012产生,结合了Ant和Maven的优点,理念是特殊领域问题方案,DSL(Domain Specific Languages)。采用Google的groovy语言编写配置脚本。约定好,灵活性高。
2.4 版本对比
(1)plugins和apply plugin
2.1语法:
2.0旧语法:
2.5指令
./gradlew -v 版本号,首次运行,没有gradle的要下载的哦。
./gradlew clean 删除HelloWord/app目录下的build文件夹
./gradlew build 检查依赖并编译打包
./gradlew assembleDebug 编译并打Debug包
./gradlew assembleRelease 编译并打Release的包
./gradlew installRelease Release模式打包并安装
./gradlew uninstallRelease 卸载Release模式包
gradle androidDependencies 找到每种buildtype下的依赖关系图
compile ''{ exclude module:'' } 排除一个库中引用的其它库
gradle build -profile Gradle性能检测
gradle task 查看Android工程有哪些Task
gradle task --all 查看各个Task的具体作用与各个Task之间的相互调用关系
gradle assemble
gradle assembleRelease
gradle assembleBug
gradle check 用于执行检查任务
gradle build 组合指令,相当于执行了check和assemble的所有工作
gradle clean 清理所有中间编译结果
gradle build -x link 禁用掉Lint
Gradle加速
1.可以在 gradle.properties 文件中增加如下所示代码
org.gradle.daemnotallow=true
org.gradle.parallel=true
org.gradle.cnotallow=true
2.同时,在build.gradle中增加如下所示的代码
dexOptions{
incremental true
javaMaxHeapSize "4g"
}
gradle增加编译内存
1.可以在 gradle.properties 文件中增加如下内存配置
Default value: -Xmx10248m -XX:MaxPermSize=256m
org.gradle.jvmargs=-Xmx2048m -XX:MaxPermSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8
使用Gradle 精简资源
1.打开快捷指令输入框,输入"remove unused resources" 进行资源精简
2.shrinkResources true
这两种检查资源的方式属于静态检测,一些动态加载的资源是无法检测的,注意不要误删
使用Gradle本地缓存
在AndroidStudio Setting-Build-Build Tools-Gradle标签中,选择Offline work,并指定默认的.gradle文件夹即可
这种方式可以让Gradle在离线的情况下进行编译,优先使用本地库
Gradle生命周期
Gradle在编译项目时有着它自己的生命周期,从编译开始到编译完毕Gradle一共要经历三个阶段
1.Initiliazation
初始化阶段,顾名思义就是执行Gradle的初始化配置选项,即执行项目中的settings.gradle脚本
2.Configration
解析每个Project中的build.gradle脚本,即解析所有Project中的编译选项。解析完毕后,Gradle就生成了一张有向关系图-taskgraph,这里面包含了整个Task的依赖关系
3.Build
最后的编译运行阶段,即按照taskgraph执行编译
2.6问题
(1)Could not resolve org.springframework.build.gradle:propdeps-plugin:0.0.7.
编译SymmetricDS时报错
解决办法:
在build.gradle文件中新增一行:
maven { url 'http://repo.springsource.org/plugins-release' }
重新运行gradle build:
(2)The task name 'symmetric-server:serverDistZip' must not contain any of the following characters: [/, \, :, <, >, ", ?, *, |].
删除build.gradle 297行的冒号
(3)Cannot add task 'wrapper' as a task with that name already exists.
解决:
把task wrapper(type: Wrapper) { gradleVersion = '2.2.1' }
改为:
前者是老版本格式,后者为新版本格式
(4)Failed to load native library 'native-platform.dll' for Windows 10 amd64.
以管理员身份运行STS或者IDEA
(5)2023-01-22T20:41:11.560+08:00 ERROR 12600[ main] o.a.catalina.core.AprLifecycleListener: An incompatible version [1.2.24] of the Apache Tomcat Native library is installed, while Tomcat requires version [1.2.34]
解决办法:到这个地址找到对应版本:1.2.34
http://archive.apache.org/dist/tomcat/tomcat-connectors/native/
下载tomcat-native-1.2.34-openssl-1.1.1o-ocsp-win32-bin.zip这个文件,找到bin\x64\tcnative-1.dll,复制到jdk的bin目录下。
3.Thymeleaf配置使用
3.1 Thymeleaf简介
根据官网介绍,Thymeleaf用于代替JSP,甚至FreeMaker。这种新服务器端Java模板引擎,适用于web应用和独立环境,能够处理HTML, XML, JavaScript, CSS,甚至纯文本。主要目标是提供一种优雅且高度可维护的创建模板的方式。基于自然模板的概念,将逻辑注入模板文件,而不影响模板用于原型设计。这提高了设计人员之间的沟通效率,并在设计和开发团队之间架起了桥梁。
Thymeleaf从设计之初就考虑到了Web标准,尤其是HTML5。还允许创建完全可验证的模板。支持HTML、XML、TEXT、JAVASCRIPT、CSS和RAW六种模板,每种模板都可以称为模板模式,包括两种标签模板模式(HTML和XML),三种文本模板模式(TEXT, JAVASCRIPT和CSS)和一种无操作模板模式(RAW)。
HTML模板模式将允许任何类型的HTML输入,包括HTML5, HTML 4和XHTML。不会执行任何验证或格式检查,并且模板代码将在输出中得到最大程度的尊重。最常用的就是这种模板,它既可以让前端工程师在浏览器中直接打开查看样式,也可以让后端工程师结合真实数据查看显示效果,同时,SpringBoot 提供了 Thymeleaf 自动化配置解决方案,因此在 SpringBoot 中使用 Thymeleaf 非常方便。除了展示基本的 HTML ,进行页面渲染之外,也可以作为一个 HTML 片段进行渲染,例如我们在做邮件发送时,可以使用 Thymeleaf 作为邮件发送模板。另外,由于 Thymeleaf 模板后缀为 .html,可以直接被浏览器打开,因此,预览时非常方便。
XML模板模式将允许XML输入。代码应该是格式化的,没有未关闭的标记、没有未加引号的属性。如果发现格式不对,解析器将抛出异常。但是,不会执行任何验证(针对DTD或XML Schema)。
TEXT模板模式将允许对非标签性质的模板使用特殊语法。例如文本电子邮件或模板化文档。注意,HTML或XML模板也可以作为TEXT处理,但是它们不会被解析为标记,并且每个标签、DOCTYPE、注释等都将被视为纯文本。
JAVASCRIPT模板模式将允许在thymleaf应用程序中处理JAVASCRIPT文件。能够在JavaScript文件中以与在HTML文件中相同的方式使用模型数据,但是限于特殊JavaScript脚本,例如专门的转义或自然脚本。JAVASCRIPT模板模式被认为是文本模式,因此使用与TEXT模板模式相同的特殊语法。
CSS模板模式将允许处理thymleaf应用程序中的CSS文件。与JAVASCRIPT模式类似,CSS模板模式也是一种文本模式,并使用来自TEXT模板模式的特殊处理语法。
RAW模板模式将根本不处理模板。它用于将未触及的资源(文件、URL响应等)插入正在处理的模板中。例如,HTML格式的外部、不受控制的资源可以包含在应用程序模板中,可以放心地知道这些资源可能包含的任何Thymeleaf代码都不会被执行。
3.2 SpringBoot和Thymeleaf配合
Spring Boot 中整合 Thymeleaf 非常容易,只需要创建项目时添加 SpringWeb和Thymeleaf 即可。最前面一节“1.1新建SpringBoot项目”选了四个组件,实际上只需要选 SpringWeb和Thymeleaf就能实现SpringBoot和Thymeleaf整合。
再来复习一遍SpringBoot和Thymeleaf整合的关键步骤:
(1)加入依赖组件
Gradle项目:在build.gradle中加入如下依赖:
implementation 'org.springframework.boot:spring-boot-starter-thymeleaf'
implementation 'org.springframework.boot:spring-boot-starter-web'
Maven项目:在POM.xml中加入如下依赖:
(2)在配置文件中修改Thymeleaf配置
在*.properties或者*.yml配置文件里修改配置,例如:
如果spring.thymeleaf.mode=LEGACYHTML5,那么需要引入:
以上这些属性是由SpringBoot自动管理的,配置管理类是
其主要代码如下:
这个配置管理类通过@ConfigurationProperties注解,将application.properties前缀为 spring.thymeleaf的配置和这个类中的属性绑定。
Spring Boot为Thymeleaf提供的自动化配置类是
其主要代码如下:
其中,@ConditionalOnClass注解的参数指明:若当前系统中存在 TemplateMode 和 SpringTemplateEngine 类,则该自动化配置类才会生效,即只要项目中引入了 Thymeleaf 相关的依赖,这个配置就会生效。
(3)编写控制器
在控制器暴露给前端的方法中,使用model.addAttribute方法把数据加入进去,如下:
这个方法返回逻辑视图名+数据,逻辑视图名为thymeleaf/smalllist,数据放在model中。
因此,我们需要在 resources/templates/thymeleaf 目录下提供一个名为 smalllist.html 的 Thymeleaf 模板文件。
(4)编写Thymeleaf模板文件
例如,模板文件smalllist.html的代码片断如下:
通过 th:each 指令来遍历一个集合,数据的展示通过 th:text 指令来实现。
3.3 Thymeleaf关键语法
3.3.1 Thymeleaf 语法规则
在使用 Thymeleaf 之前,首先要在页面的 html 标签中声明名称空间,示例代码如下。
在 html 标签中声明此名称空间,可避免编辑器出现 html 验证错误,但这一步并非必须进行的,即使我们不声明该命名空间,也不影响 Thymeleaf 的使用。
Thymeleaf 作为一种模板引擎,它拥有自己的语法规则。Thymeleaf 语法分为以下 2 类:
3.3.1.1 标准表达式语法
Thymeleaf 模板引擎支持多种表达式:
1、变量表达式${...}
使用 ${} 包裹的表达式被称为变量表达式,该表达式具有以下功能:
- 获取对象的属性和方法
- 使用内置的基本对象
- 使用内置的工具对象
(1)获取对象的属性和方法
使用变量表达式可以获取对象的属性和方法,例如,获取 person 对象的 lastName 属性,表达式形式如下:
(2)基本对象
使用变量表达式还可以使用内置基本对象,获取内置对象的属性,调用内置对象的方法。 Thymeleaf 中常用的内置基本对象如下:
- #ctx :上下文对象;
- #vars :上下文变量;
- #locale:上下文的语言环境;
- #request:HttpServletRequest 对象(仅在 Web 应用中可用);
- #response:HttpServletResponse 对象(仅在 Web 应用中可用);
- #session:HttpSession 对象(仅在 Web 应用中可用);
- #servletContext:ServletContext 对象(仅在 Web 应用中可用)。
例如,我们通过以下 2 种形式,都可以获取到 session 对象中的 map 属性:
(3)内置工具
除了能使用内置的基本对象外,变量表达式还可以使用一些内置的工具对象。
- strings:字符串工具对象,常用方法有:equals、equalsIgnoreCase、length、trim、toUpperCase、toLowerCase、indexOf、substring、replace、startsWith、endsWith,contains 和 containsIgnoreCase 等;
- numbers:数字工具对象,常用的方法有:formatDecimal 等;
- bools:布尔工具对象,常用的方法有:isTrue 和 isFalse 等;
- arrays:数组工具对象,常用的方法有:toArray、length、isEmpty、contains 和 containsAll 等;
- lists/sets:List/Set 集合工具对象,常用的方法有:toList、size、isEmpty、contains、containsAll 和 sort 等;
- maps:Map 集合工具对象,常用的方法有:size、isEmpty、containsKey 和 containsValue 等;
- dates:日期工具对象,常用的方法有:format、year、month、hour 和 createNow 等。
例如,我们可以使用内置工具对象 strings 的 equals 方法,来判断字符串与对象的某个属性是否相等,代码如下。
2、选择变量表达式*{...}
选择变量表达式与变量表达式功能基本一致,只是在变量表达式的基础上增加了与 th:object 的配合使用。当使用 th:object 存储一个对象后,我们可以在其后代中使用选择变量表达式({...})获取该对象中的属性,其中,“”即代表该对象。
th:object 用于存储一个临时变量,该变量只在该标签及其后代中有效,在后面的内容“th 属性”中我详细介绍。
3、链接表达式@{...}
不管是静态资源的引用,还是 form 表单的请求,凡是链接都可以用链接表达式 (@{...})。
链接表达式的形式结构如下:
- 无参请求:@{/xxx}
- 有参请求:@{/xxx(k1=v1,k2=v2)}
例如使用链接表达式引入 css 样式表,代码如下。
4、国际化表达式#{...}
消息表达式一般用于国际化的场景。结构如下。
注意:此处了解即可,我们会在后面的章节中详细介绍。
5、片段引用表达式~{...}
片段引用表达式用于在模板页面中引用其他的模板片段,该表达式支持以下 2 中语法结构:
- 推荐:~{templatename::fragmentname}
- 支持:~{templatename::#id}
以上语法结构说明如下:
- templatename:模版名,Thymeleaf 会根据模版名解析完整路径:/resources/templates/templatename.html,要注意文件的路径。
- fragmentname:片段名,Thymeleaf 通过 th:fragment 声明定义代码块,即:th:fragment="fragmentname"
- id:HTML 的 id 选择器,使用时要在前面加上 # 号,不支持 class 选择器。
3.3.1.2 th属性
Thymeleaf 还提供了大量的 th 属性,这些属性可以直接在 HTML 标签中使用,其中常用 th 属性及其示例如下表。
3.3.2 Thymeleaf 公共页面抽取
Thymeleaf 作为一种优雅且高度可维护的模板引擎,同样支持公共页面的抽取和引用。我们可以将公共页面片段抽取出来,存放到一个独立的页面中,并使用 Thymeleaf 提供的 th:fragment 属性为这些抽取出来的公共页面片段命名。
将公共页面片段抽取出来,存放在 commons.html 中,代码如下。
3.3.2.1 引用公共页面
在 Thymeleaf 中,我们可以使用以下 3 个属性,将公共页面片段引入到当前页面中。
- th:insert:将代码块片段整个插入到使用了 th:insert 属性的 HTML 标签中;
- th:replace:将代码块片段整个替换使用了 th:replace 属性的 HTML 标签中;
- th:include:将代码块片段包含的内容插入到使用了 th:include 属性的 HTML 标签中。
使用上 3 个属性引入页面片段,都可以通过以下 2 种方式实现。
- ~{templatename::selector}:模板名::选择器
- ~{templatename::fragmentname}:模板名::片段名
通常情况下,~{} 可以省略,其行内写法为 [[~{...}]] 或 [(~{...})],其中 [[~{...}]] 会转义特殊字符,[(~{...})] 则不会转义特殊字符。
(1)在页面 fragment.html 中引入 commons.html 中声明的页面片段,可以通过以下方式实现:
(2)启动 Spring Boot,使用浏览器访问 fragment.html,查看源码,结果如下:
3.3.2.2 传递参数
Thymeleaf 在抽取和引入公共页面片段时,还可以进行参数传递,大致步骤如下:
(1)传入参数
引用公共页面片段时,我们可以通过以下
- 模板名::选择器名或片段名(参数1=参数值1,参数2=参数值2)
- 模板名::选择器名或片段名(参数值1,参数值2)
注:若传入参数较少时,一般采用第二种方式,直接将参数值传入页面片段中;若参数较多时,建议使用第一种方式,明确指定参数名和参数值,。
(2)使用参数
在声明页面片段时,我们可以在片段中声明并使用这些参数,例如:
3.4 模板语言对比
模板语言 |
特点 |
jsp |
Java Server Pages,动态网页技术,由应用服务器中的JSP引擎来编译和执行,再将生成的整个页面返回给客户端。支持表达式语言(EL、JSTL)。因为其是在服务器端渲染的,消耗性能,所以springboot项目中不在推荐使用jsp |
freemarker |
文件一般保存为 xxx.ftl,严格依赖MVC模式,不依赖Servlet容器(不占用JVM内存),其语法对比thymeleaf较为复杂 |
thymeleaf |
springboot示例常用的模板引擎,轻量级的模板引擎(负责逻辑业务的不推荐,解析DOM或者XML会占用多的内存)。可以直接在浏览器中打开且正确显示,表达式并不会影响,模板页面文件以html结尾 |