SpringBoot+Gradle+Thymeleaf搭配会如何——快速入门JAVA模板开发

时间:2023-01-28 17:01:45

前言:Thymeleaf是新一代Java模板引擎,基于自然模板的理念让其既适合原型设计,又适合开发测试,同时,对于广大JSP程序员来说,上手非常容易。但是,很多新程序员还是存在一些学习障碍。本文结合SpringBoot和Gradle来逐步介绍Thymeleaf关键知识点,只要一天就能真正入门。


1.按部就班开发大表查询应用程序


下面给出一个实例来巩固相关知识。我们的实例使用STS 4.17(IDEA下类似)。


1.1新建Spring Boot项目


使用Spring Starter Project向导来新建源代码工程项目:

SpringBoot+Gradle+Thymeleaf搭配会如何——快速入门JAVA模板开发


SpringBoot+Gradle+Thymeleaf搭配会如何——快速入门JAVA模板开发



1.2检查配置文件build.gradle


Spring Starter Project默认创建了build.gradle,里面引用了四个组件:Spring Web,Spring Configuration Processor,Thymeleaf,Lombok,如下:

plugins {
id 'java'
id 'org.springframework.boot' version '2.6.14'
id 'io.spring.dependency-management' version '1.0.15.RELEASE'
}
group = 'work.metanet'
version = '0.0.1-SNAPSHOT'
sourceCompatibility = '1.8'
repositories {
mavenCentral()
}
dependencies {
implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
implementation 'org.springframework.boot:spring-boot-starter-thymeleaf'
implementation 'org.springframework.boot:spring-boot-starter-web'
implementation 'org.springframework.boot:spring-boot-configuration-processor'
implementation 'mysql:mysql-connector-java:5.1.49'
implementation 'org.projectlombok:lombok:1.18.24'
testImplementation 'org.springframework.boot:spring-boot-starter-test'
}
tasks.named('test') {
useJUnitPlatform()
}

SpringBoot+Gradle+Thymeleaf搭配会如何——快速入门JAVA模板开发



1.3前端页面


1.3.1新增html文件:index.html


在resource/templates/thymeleaf下面新增html文件:index.html

<!DOCTYPE html>
<html>
<head>
<title>前端开发演示</title>
<meta http-equiv="Content-Type" cnotallow="text/html; charset=UTF-8" />
</head>
<body>
<h2>使用Spring Web (MVC模式)</h2>
<ul>
<li>
<ul>
<li><a th:href="@{/thymeleaf}">首页</a></li>
<li><a th:href="@{/smalllist.thymeleaf}">小列表</a></li>
<li><a th:href="@{/biglist.thymeleaf}">大列表</a></li>
</ul>
</li>
</ul>
<p>模板引擎: <strong>Thymeleaf</strong>使用说明</p>
<img th:src="@{/images/TH属性介绍1.png}">
<img th:src="@{/images/TH属性介绍2.png}">
<img th:src="@{/images/TH属性介绍3.png}">
<p><span>当前时间:</span><img th:src="@{/images/thymeleaf_logo.png}"></p>
</body>
</html>


SpringBoot+Gradle+Thymeleaf搭配会如何——快速入门JAVA模板开发



  • @{}变量表达式用于获取当前上下文路径。
  • /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


<!DOCTYPE html>
<html>
<head>
<title>前端开发演示</title>
<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 td{border:1px solid #000;height:25px; text-align:left; border-left:1px;}
table th{text-align:left; background:#edd3d4; color:#a10333; border:#000 solid 1px; white-space:nowrap; height:21px; border-top:1px;border-left:1px;}
</style>
</head>
<body>
<h2>小列表(1030 条)</h2>
<p>模板引擎: <strong>Thymeleaf</strong>;持久层:<strong>JPA</strong>;数据库:<strong>Mysql</strong>;操作:<strong>大数据列表查询</strong></p>
<table>
<thead>
<tr>
<th>设备id</th>
<th>设备名称</th>
<th>有线mac</th>
<th>无线mac</th>
<th>IMEI号</th>
<th>IMEI2号</th>
<th>蓝牙</th>
<th>终端序列号</th>
<th>终端uuid</th>
<th>品牌id</th>
<th>型号id</th>
<th>固件信息</th>
<th>0导入/1记录</th>
<th>0禁用/1启用</th>
<th>备注</th>
<th>创建时间</th>
<th>修改时间</th>
<th>创建者id</th>
<th>修改者id</th>
<th>0无效/1有效</th>
<th>0虚拟/1真实</th>
</tr>
</thead>
<tbody>
<tr th:each="e : ${entries}">
<td th:text="${e.deviceId}">...</td>
<td th:text="${e.deviceName}">...</td>
<td th:text="${e.wiredMac}">...</td>
<td th:text="${e.wirelessMac}">...</td>
<td th:text="${e.imei}">...</td>
<td th:text="${e.imei2}">...</td>
<td th:text="${e.bluetooth}">...</td>
<td th:text="${e.serialNumber}">...</td>
<td th:text="${e.uuid}">...</td>
<td th:text="${e.brandId}">...</td>
<td th:text="${e.modelId}">...</td>
<td th:text="${e.firmwareInfo}">...</td>
<td th:text="${e.source}">...</td>
<td th:text="${e.enableStatus}">...</td>
<td th:text="${e.remark}">...</td>
<td th:text="${e.createTime}">...</td>
<td th:text="${e.updateTime}">...</td>
<td th:text="${e.createUser}">...</td>
<td th:text="${e.updateUser}">...</td>
<td th:text="${e.status}">...</td>
<td th:text="${e.tag}">...</td>
</tr>
</tbody>
</table>
</body>
</html>

SpringBoot+Gradle+Thymeleaf搭配会如何——快速入门JAVA模板开发


其中,

  • <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


<!DOCTYPE html>
<html>
<head>
<title>前端开发演示</title>
<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 td{border:1px solid #000;height:25px; text-align:left; border-left:1px;}
table th{text-align:left; background:#edd3d4; color:#a10333; border:#000 solid 1px; white-space:nowrap; height:21px; border-top:1px;border-left:1px;}
</style>
</head>
<body>
<h2>大列表</h2>
<p>模板引擎: <strong>Thymeleaf</strong>;持久层:<strong>JPA</strong>;数据库:<strong>Mysql</strong>;操作:<strong>大数据列表查询</strong></p>
<table>
<thead>
<tr>
<th>设备id</th>
<th>设备名称</th>
<th>有线mac</th>
<th>无线mac</th>
<th>IMEI号</th>
<th>IMEI2号</th>
<th>蓝牙</th>
<th>终端序列号</th>
<th>终端uuid</th>
<th>品牌id</th>
<th>型号id</th>
<th>固件信息</th>
<th>0导入/1记录</th>
<th>0禁用/1启用</th>
<th>备注</th>
<th>创建时间</th>
<th>修改时间</th>
<th>创建者id</th>
<th>修改者id</th>
<th>0无效/1有效</th>
<th>0虚拟/1真实</th>
</tr>
</thead>
<tbody>
<tr th:each="e : ${dataSource}">
<td th:text="${e.deviceId}">...</td>
<td th:text="${e.deviceName}">...</td>
<td th:text="${e.wiredMac}">...</td>
<td th:text="${e.wirelessMac}">...</td>
<td th:text="${e.imei}">...</td>
<td th:text="${e.imei2}">...</td>
<td th:text="${e.bluetooth}">...</td>
<td th:text="${e.serialNumber}">...</td>
<td th:text="${e.uuid}">...</td>
<td th:text="${e.brandId}">...</td>
<td th:text="${e.modelId}">...</td>
<td th:text="${e.firmwareInfo}">...</td>
<td th:text="${e.source}">...</td>
<td th:text="${e.enableStatus}">...</td>
<td th:text="${e.remark}">...</td>
<td th:text="${e.createTime}">...</td>
<td th:text="${e.updateTime}">...</td>
<td th:text="${e.createUser}">...</td>
<td th:text="${e.updateUser}">...</td>
<td th:text="${e.status}">...</td>
<td th:text="${e.tag}">...</td>
</tr>
</tbody>
</table>
</body>
</html>

SpringBoot+Gradle+Thymeleaf搭配会如何——快速入门JAVA模板开发


这个文件和smalllist.html类似,区别在于后台返回的对象是dataSource


1.4新增后台类


1.4.1新增model类Device


在STS的new菜单下点class,出现下图:

SpringBoot+Gradle+Thymeleaf搭配会如何——快速入门JAVA模板开发


新增属性和注解,如下:

@Entity(name="t_device")
@Data
@ToString
@AllArgsConstructor
@NoArgsConstructor
public class Device {
/**
* 设备ID
*/
@Id
private String deviceId;
/**
* 设备名称
*/
private String deviceName;
/**
* MAC地址
*/
private String wiredMac;
/**
* 无线MAC地址
*/
private String wirelessMac;
/**
* IMEI
*/
private String imei;
/**
* IMEI2
*/
private String imei2;
/**
* 蓝牙
*/
private String bluetooth;
/**
* 序列号
*/
private String serialNumber;
/**
* UUID
*/
private String uuid;
/**
* 品牌ID
*/
private String brandId;
/**
* 型号ID
*/
private String modelId;
/**
* 固件信息
*/
private String firmwareInfo;
/**
* 来源 0导入/1记录
*/
private String source;
/**
* 启用状态 0禁用/1启用
*/
private String enableStatus;
/**
* 备注
*/
private String remark;
/**
* 创建时间
*/
private String createTime;
/**
* 修改时间
*/
private String updateTime;
/**
* 创建用户
*/
private String createUser;
/**
* 修改用户
*/
private String updateUser;
/**
* 状态 0无效/1有效
*/
private String status;
/**
* 真实标签 0虚拟/1真实
*/
private String tag;
}

1.4.2新增控制器


在new菜单下点class:

SpringBoot+Gradle+Thymeleaf搭配会如何——快速入门JAVA模板开发


在控制器中新增方法和注解,如下:

@Controller
public class DeviceController {
@Autowired
private DeviceRepository deviceRepository;
public DeviceController() {
super();
}
@GetMapping({"/", "/thymeleaf"})
public String index() {
return "thymeleaf/index";
}
@RequestMapping("/smalllist.thymeleaf")
public String smallList(final Model model) {
final List<Device> baseList = deviceRepository.findAll();
model.addAttribute("entries", baseList.iterator());
return "thymeleaf/smalllist";
}
@RequestMapping("/biglist.thymeleaf")
public String bigList(final Model model) {
final List<Device> baseList = deviceRepository.findAll();
final Iterator<Device> deviceEntries = new Iterator<Device>() {
private static final int REPEATS = 300;
private int repeatCount = 0;
private Iterator<Device> currentIterator = null;
@Override
public boolean hasNext() {
if (this.currentIterator != null && this.currentIterator.hasNext()) {
return true;
}
if (this.repeatCount < REPEATS) {
this.currentIterator = baseList.iterator();
this.repeatCount++;
return true;
}
return false;
}
@Override
public Device next() {
return this.currentIterator.next();
}
};
model.addAttribute("dataSource", deviceEntries);
return "thymeleaf/biglist";
}
}

1.4.3新增JPA仓库类


在new下点interface:

SpringBoot+Gradle+Thymeleaf搭配会如何——快速入门JAVA模板开发


新增方法,如下:

public interface DeviceRepository extends JpaRepository<Device, String> {
public List<Device> findAll();
}

其中,DeviceRepository 继承了JpaRepository

JpaRepository归属于Spring Data JPA组件,JpaRepository在Spring Data体系的位置如下图所示:

SpringBoot+Gradle+Thymeleaf搭配会如何——快速入门JAVA模板开发


说明继承关系的类图如下:

SpringBoot+Gradle+Thymeleaf搭配会如何——快速入门JAVA模板开发


JpaRepository的主要方法如下:

SpringBoot+Gradle+Thymeleaf搭配会如何——快速入门JAVA模板开发


我们在DeviceRepository里面只提供了findAll()方法,该方法用于查询所有记录。


1.4.4启动和测试


在Boot Dashboard中启动应用:

SpringBoot+Gradle+Thymeleaf搭配会如何——快速入门JAVA模板开发


在浏览器中输入地址:

​http://localhost:8080/​

SpringBoot+Gradle+Thymeleaf搭配会如何——快速入门JAVA模板开发


点小列表,如下:

SpringBoot+Gradle+Thymeleaf搭配会如何——快速入门JAVA模板开发

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/

如下:

SpringBoot+Gradle+Thymeleaf搭配会如何——快速入门JAVA模板开发


选择gradle-7.6-bin.zip,解压到D:\gradle\gradle-7.6

SpringBoot+Gradle+Thymeleaf搭配会如何——快速入门JAVA模板开发


对于windows 10操作系统,打开“编辑系统环境变量”:

SpringBoot+Gradle+Thymeleaf搭配会如何——快速入门JAVA模板开发


进入“环境变量”,新增:

GRADLE_HOME= D:\gradle\gradle-7.6


SpringBoot+Gradle+Thymeleaf搭配会如何——快速入门JAVA模板开发


再修改Path增加%GRADLE_HOME%\bin

使用gradle –v验证版本:

SpringBoot+Gradle+Thymeleaf搭配会如何——快速入门JAVA模板开发



可以通过环境变量指定本地仓库:

GRADLE_USER_HOME=f:\maven-repository

SpringBoot+Gradle+Thymeleaf搭配会如何——快速入门JAVA模板开发


2.2配置和启动


(1)远程仓库配置

全局远程仓库配置:在文件夹D:\gradle\gradle-7.6\init.d中新建文件init.gradle,填充以下内容:

allprojects{
repositories {
maven{
allowInsecureProtocol =true
url='https://maven.aliyun.com/repository/public'
}

def REPOSITORY_URL = 'https://maven.aliyun.com/repository/public/'
//做一些国外不稳定地址的替换
all {
ArtifactRepository repo ->
if (repo instanceof MavenArtifactRepository) {
def url = repo.url.toString()
if (url.startsWith('https://artifacts.elastic.co/maven')
||url.startsWith('https://repo1.maven.org/maven2')
|| url.startsWith('https://repo.maven.org/maven2')
|| url.startsWith('https://jcenter.bintray.com/')
||url.startsWith('https://repo.maven.apache.org/maven2')
) {
project.logger.lifecycle "Repository ${repo.url} replaced by $REPOSITORY_URL."
remove repo
}
}
}
}
}

(2)代码工程(项目)仓库配置

build.gradle文件是配置项目中要使用的gradle库文件,和Maven工程中的pom.xml相同。

可添加本项目的仓库配置:

repositories {
maven {
url 'http://maven.aliyun.com/nexus/content/groups/public/'
}
mavenCentral()
}

下面描述POM和build.gradle的映射方法。假设pom.xml中的依赖:


<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>5.0.8.RELEASE</version>
</dependency>

build.gradle中的依赖:

dependencies {
api 'org.springframework:spring-core:5.0.8.RELEASE'
}

更新build.gradle:项目右键,点Gradle-->Refresh Gradle Project。

然后,增加一句:api 'org.apache.commons:commons-lang3:3.8.1'

重新更新build.gradle后自动下载,如下图:

SpringBoot+Gradle+Thymeleaf搭配会如何——快速入门JAVA模板开发

完成后增加一个类CheckNum来试试包依赖是否成功加入,如下图:

SpringBoot+Gradle+Thymeleaf搭配会如何——快速入门JAVA模板开发

运行后,如下图:

SpringBoot+Gradle+Thymeleaf搭配会如何——快速入门JAVA模板开发

项目中依赖库也会显示出来:

SpringBoot+Gradle+Thymeleaf搭配会如何——快速入门JAVA模板开发

刷新项目时先检查本地仓库是否存在依赖包,不存在这从互联网上的远程库中下载到本地仓库。

本地仓库默认路径为: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:

SpringBoot+Gradle+Thymeleaf搭配会如何——快速入门JAVA模板开发


在互联网仓库中查看commons-lang3,地址为:

https://mvnrepository.com/artifact/org.apache.commons/commons-lang3

在eclipse-->new-->project…中新建一个demo项目,如下:

SpringBoot+Gradle+Thymeleaf搭配会如何——快速入门JAVA模板开发


下一步显示关于集成的说明,再下一步如下:

SpringBoot+Gradle+Thymeleaf搭配会如何——快速入门JAVA模板开发

点下一步,可以选择覆盖工作区设置,提供自己安装的gradle发布版,可以指定其本地安装路径,如下:

SpringBoot+Gradle+Thymeleaf搭配会如何——快速入门JAVA模板开发

点configure workspace settings…显示各项目通用的工作区的gradle设置界面:

SpringBoot+Gradle+Thymeleaf搭配会如何——快速入门JAVA模板开发

如果在specific gradle version选择的gradle版本没有安装,eclipse会自动安装,但是由于国外网站,可能会导致下载速度很慢,所以,先前在init.gradle文件中做了一些国外不稳定的地址链接的替换。

最后显示preview,如下:

SpringBoot+Gradle+Thymeleaf搭配会如何——快速入门JAVA模板开发

目录结构如下:

SpringBoot+Gradle+Thymeleaf搭配会如何——快速入门JAVA模板开发


  • 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语法:

plugins {
id "org.springframework.boot" version "2.1.0.RELEASE"
}

2.0旧语法:

buildscript {
ext {
springBootVersion = '2.1.0.RELEASE'
}
repositories {
mavenCentral()
}
dependencies {
classpath("org.springframework.boot:spring-boot-gradle-plugin:${springBootVersion}")
}
}

apply plugin: 'org.springframework.boot'

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时报错


SpringBoot+Gradle+Thymeleaf搭配会如何——快速入门JAVA模板开发

解决办法:

build.gradle文件中新增一行:

maven { url 'http://repo.springsource.org/plugins-release' }

SpringBoot+Gradle+Thymeleaf搭配会如何——快速入门JAVA模板开发

重新运行gradle build:

SpringBoot+Gradle+Thymeleaf搭配会如何——快速入门JAVA模板开发

(2)The task name 'symmetric-server:serverDistZip' must not contain any of the following characters: [/, \, :, <, >, ", ?, *, |].

SpringBoot+Gradle+Thymeleaf搭配会如何——快速入门JAVA模板开发

删除build.gradle 297行的冒号

(3)Cannot add task 'wrapper' as a task with that name already exists.

SpringBoot+Gradle+Thymeleaf搭配会如何——快速入门JAVA模板开发

解决:

把task wrapper(type: Wrapper) { gradleVersion = '2.2.1' }

改为:

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、JAVASCRIPTCSSRAW六种模板,每种模板都可以称为模板模式,包括两种标签模板模式(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中加入如下依赖:

SpringBoot+Gradle+Thymeleaf搭配会如何——快速入门JAVA模板开发

(2)在配置文件中修改Thymeleaf配置

在*.properties或者*.yml配置文件里修改配置,例如:

# 在呈现模板之前检查模板是否存在,默认true
spring.thymeleaf.check-template=false
# thymeleaf模板文件前缀,默认为classpath:/templates/
spring.thymeleaf.prefix=classpath:/templates/
# thymeleaf模板文件后缀,默认.html
spring.thymeleaf.suffix=.html
# 视图模板类型,默认HTML
spring.thymeleaf.mode=HTML
# 默认视图编码格式,默认UTF-8
spring.thymeleaf.encoding=UTF-8
# 响应类型,默认text/html
spring.thymeleaf.servlet.content-type=text/html
# 配置页面缓存,默认true,若页面不能及时刷新,需要关闭
spring.thymeleaf.cache=false

如果spring.thymeleaf.mode=LEGACYHTML5,那么需要引入:

implementation 'net.sourceforge.nekohtml:nekohtml'

以上这些属性是由SpringBoot自动管理的,配置管理类是

org.springframework.boot.autoconfigure.thymeleaf.ThymeleafProperties

其主要代码如下:

SpringBoot+Gradle+Thymeleaf搭配会如何——快速入门JAVA模板开发

这个配置管理类通过@ConfigurationProperties注解,将application.properties前缀为 spring.thymeleaf的配置和这个类中的属性绑定。

Spring Boot为Thymeleaf提供的自动化配置类是

org.springframework.boot.autoconfigure.thymeleaf.ThymeleafAutoConfiguration

其主要代码如下:

@Configuration
@EnableConfigurationProperties(ThymeleafProperties.class)
@ConditionalOnClass({TemplateMode.class, SpringTemplateEngine.class})
@AutoConfigureAfter({WebMvcAutoConfiguration.class, WebFluxAutoConfiguration.class})
public class ThymeleafAutoConfiguration {
//....
}

其中,@ConditionalOnClass注解的参数指明:若当前系统中存在 TemplateMode 和 SpringTemplateEngine 类,则该自动化配置类才会生效,即只要项目中引入了 Thymeleaf 相关的依赖,这个配置就会生效。

(3)编写控制器

在控制器暴露给前端的方法中,使用model.addAttribute方法把数据加入进去,如下:

SpringBoot+Gradle+Thymeleaf搭配会如何——快速入门JAVA模板开发

这个方法返回逻辑视图名+数据,逻辑视图名为thymeleaf/smalllist,数据放在model中。

因此,我们需要在 resources/templates/thymeleaf 目录下提供一个名为 smalllist.html 的 Thymeleaf 模板文件。

4编写Thymeleaf模板文件

例如,模板文件smalllist.html的代码片断如下:

SpringBoot+Gradle+Thymeleaf搭配会如何——快速入门JAVA模板开发

通过 th:each 指令来遍历一个集合,数据的展示通过 th:text 指令来实现。


3.3 Thymeleaf关键语法


3.3.1 Thymeleaf 语法规则


在使用 Thymeleaf 之前,首先要在页面的 html 标签中声明名称空间,示例代码如下。

xmlns:th="http://www.thymeleaf.org"

在 html 标签中声明此名称空间,可避免编辑器出现 html 验证错误,但这一步并非必须进行的,即使我们不声明该命名空间,也不影响 Thymeleaf 的使用。

Thymeleaf 作为一种模板引擎,它拥有自己的语法规则。Thymeleaf 语法分为以下 2 类:


3.3.1.1 标准表达式语法

Thymeleaf 模板引擎支持多种表达式:

1、变量表达式${...}

使用 ${} 包裹的表达式被称为变量表达式,该表达式具有以下功能:

  1. 获取对象的属性和方法
  2. 使用内置的基本对象
  3. 使用内置的工具对象

(1)获取对象的属性和方法

使用变量表达式可以获取对象的属性和方法,例如,获取 person 对象的 lastName 属性,表达式形式如下:

${person.lastName}

(2)基本对象

使用变量表达式还可以使用内置基本对象,获取内置对象的属性,调用内置对象的方法。 Thymeleaf 中常用的内置基本对象如下:

  1. #ctx :上下文对象;
  2. #vars :上下文变量;
  3. #locale:上下文的语言环境;
  4. #request:HttpServletRequest 对象(仅在 Web 应用中可用);
  5. #response:HttpServletResponse 对象(仅在 Web 应用中可用);
  6. #session:HttpSession 对象(仅在 Web 应用中可用);
  7. #servletContext:ServletContext 对象(仅在 Web 应用中可用)。

例如,我们通过以下 2 种形式,都可以获取到 session 对象中的 map 属性:

${#session.getAttribute('map')}
${session.map}

(3)内置工具

除了能使用内置的基本对象外,变量表达式还可以使用一些内置的工具对象。

  1. strings:字符串工具对象,常用方法有:equals、equalsIgnoreCase、length、trim、toUpperCase、toLowerCase、indexOf、substring、replace、startsWith、endsWith,contains 和 containsIgnoreCase 等;
  2. numbers:数字工具对象,常用的方法有:formatDecimal 等;
  3. bools:布尔工具对象,常用的方法有:isTrue 和 isFalse 等;
  4. arrays:数组工具对象,常用的方法有:toArray、length、isEmpty、contains 和 containsAll 等;
  5. lists/sets:List/Set 集合工具对象,常用的方法有:toList、size、isEmpty、contains、containsAll 和 sort 等;
  6. maps:Map 集合工具对象,常用的方法有:size、isEmpty、containsKey 和 containsValue 等;
  7. dates:日期工具对象,常用的方法有:format、year、month、hour 和 createNow 等。

例如,我们可以使用内置工具对象 strings 的 equals 方法,来判断字符串与对象的某个属性是否相等,代码如下。

${#strings.equals('程序员',name)}

2、选择变量表达式*{...}

选择变量表达式与变量表达式功能基本一致,只是在变量表达式的基础上增加了与 th:object 的配合使用。当使用 th:object 存储一个对象后,我们可以在其后代中使用选择变量表达式({...})获取该对象中的属性,其中,“”即代表该对象。

<div th:object="${session.user}" >
<p th:text="*{fisrtName}">firstname</p>
</div>

th:object 用于存储一个临时变量,该变量只在该标签及其后代中有效,在后面的内容“th 属性”中我详细介绍。

3、链接表达式@{...}

不管是静态资源的引用,还是 form 表单的请求,凡是链接都可以用链接表达式 (@{...})。

链接表达式的形式结构如下:

  1. 无参请求:@{/xxx}
  2. 有参请求:@{/xxx(k1=v1,k2=v2)}

例如使用链接表达式引入 css 样式表,代码如下。

<link href="asserts/css/signin.css" th:href="@{/asserts/css/signin.css}" rel="stylesheet">

4、国际化表达式#{...}

消息表达式一般用于国际化的场景。结构如下。

th:text="#{msg}"

注意:此处了解即可,我们会在后面的章节中详细介绍。

5、片段引用表达式~{...}

片段引用表达式用于在模板页面中引用其他的模板片段,该表达式支持以下 2 中语法结构:

  1. 推荐:~{templatename::fragmentname}
  2. 支持:~{templatename::#id}

以上语法结构说明如下:

  1. templatename:模版名,Thymeleaf 会根据模版名解析完整路径:/resources/templates/templatename.html,要注意文件的路径。
  2. fragmentname:片段名,Thymeleaf 通过 th:fragment 声明定义代码块,即:th:fragment="fragmentname"
  3. id:HTML 的 id 选择器,使用时要在前面加上 # 号,不支持 class 选择器。

3.3.1.2 th属性

Thymeleaf 还提供了大量的 th 属性,这些属性可以直接在 HTML 标签中使用,其中常用 th 属性及其示例如下表。

SpringBoot+Gradle+Thymeleaf搭配会如何——快速入门JAVA模板开发

SpringBoot+Gradle+Thymeleaf搭配会如何——快速入门JAVA模板开发

SpringBoot+Gradle+Thymeleaf搭配会如何——快速入门JAVA模板开发


3.3.2 Thymeleaf 公共页面抽取


Thymeleaf 作为一种优雅且高度可维护的模板引擎,同样支持公共页面的抽取和引用。我们可以将公共页面片段抽取出来,存放到一个独立的页面中,并使用 Thymeleaf 提供的 th:fragment 属性为这些抽取出来的公共页面片段命名。

将公共页面片段抽取出来,存放在 commons.html 中,代码如下。

<div th:fragment="fragment-name" >
<span>公共页面片段</span>
</div>

3.3.2.1 引用公共页面

在 Thymeleaf 中,我们可以使用以下 3 个属性,将公共页面片段引入到当前页面中。

  1. th:insert:将代码块片段整个插入到使用了 th:insert 属性的 HTML 标签中;
  2. th:replace:将代码块片段整个替换使用了 th:replace 属性的 HTML 标签中;
  3. th:include:将代码块片段包含的内容插入到使用了 th:include 属性的 HTML 标签中。

使用上 3 个属性引入页面片段,都可以通过以下 2 种方式实现。

  1. ~{templatename::selector}:模板名::选择器
  2. ~{templatename::fragmentname}:模板名::片段名

通常情况下,~{} 可以省略,其行内写法为 [[~{...}]] 或 [(~{...})],其中 [[~{...}]] 会转义特殊字符,[(~{...})] 则不会转义特殊字符。

(1)在页面 fragment.html 中引入 commons.html 中声明的页面片段,可以通过以下方式实现:

<!--th:insert 片段名引入-->
<div th:insert="commons::fragment-name"></div>
<!--th:insert id 选择器引入-->
<div th:insert="commons::#fragment-id"></div>


<!--th:replace 片段名引入-->
<div th:replace="commons::fragment-name"></div>
<!--th:replace id 选择器引入-->
<div th:replace="commons::#fragment-id"></div>


<!--th:include 片段名引入-->
<div th:include="commons::fragment-name"></div>
<!--th:include id 选择器引入-->
<div th:include="commons::#fragment-id"></div>

(2)启动 Spring Boot,使用浏览器访问 fragment.html,查看源码,结果如下:

<!--th:insert 片段名引入-->
<div>
<div >
<span>公共页面片段</span>
</div>
</div>
<!--th:insert id 选择器引入-->
<div>
<div >
<span>公共页面片段</span>
</div>
</div>


<!--th:replace 片段名引入-->
<div >
<span>公共页面片段</span>
</div>
<!--th:replace id 选择器引入-->
<div >
<span>公共页面片段</span>
</div>


<!--th:include 片段名引入-->
<div>
<span>公共页面片段</span>
</div>
<!--th:include id 选择器引入-->
<div>
<span>公共页面片段</span>
</div>

3.3.2.2 传递参数

Thymeleaf 在抽取和引入公共页面片段时,还可以进行参数传递,大致步骤如下:

(1)传入参数

引用公共页面片段时,我们可以通过以下

  1. 模板名::选择器名或片段名(参数1=参数值1,参数2=参数值2)
  2. 模板名::选择器名或片段名(参数值1,参数值2)

注:若传入参数较少时,一般采用第二种方式,直接将参数值传入页面片段中;若参数较多时,建议使用第一种方式,明确指定参数名和参数值,。

<!--th:insert 片段名引入-->
<div th:insert="commons::fragment-name(var1='insert-name',var2='insert-name2')"></div>
<!--th:insert id 选择器引入-->
<div th:insert="commons::#fragment-id(var1='insert-id',var2='insert-id2')"></div>
<!--th:replace 片段名引入-->
<div th:replace="commons::fragment-name(var1='replace-name',var2='replace-name2')"></div>
<!--th:replace id 选择器引入-->
<div th:replace="commons::#fragment-id(var1='replace-id',var2='replace-id2')"></div>


<!--th:include 片段名引入-->
<div th:include="commons::fragment-name(var1='include-name',var2='include-name2')"></div>
<!--th:include id 选择器引入-->
<div th:include="commons::#fragment-id(var1='include-id',var2='include-id2')"></div>

(2)使用参数

在声明页面片段时,我们可以在片段中声明并使用这些参数,例如:

<!--使用 var1 和 var2 声明传入的参数,并在该片段中直接使用这些参数 -->
<div th:fragment="fragment-name(var1,var2)" >
<p th:text="'参数1:'+${var1} + '-------------------参数2:' + ${var2}">...</p>
</div>


3.4 模板语言对比

模板语言

特点

jsp

Java Server Pages,动态网页技术,由应用服务器中的JSP引擎来编译和执行,再将生成的整个页面返回给客户端。支持表达式语言(EL、JSTL)。因为其是在服务器端渲染的,消耗性能,所以springboot项目中不在推荐使用jsp

freemarker

文件一般保存为 xxx.ftl,严格依赖MVC模式,不依赖Servlet容器(不占用JVM内存),其语法对比thymeleaf较为复杂

thymeleaf

springboot示例常用的模板引擎,轻量级的模板引擎(负责逻辑业务的不推荐,解析DOM或者XML会占用多的内存)。可以直接在浏览器中打开且正确显示,表达式并不会影响,模板页面文件以html结尾