目录
一、前置说明
二、Gradle 启动!
2.1、安装
2.2、初始化项目
2.3、gradle 项目目录介绍
2.4、Gradle 项目下载慢?(万能解决办法)
2.5、Gradle 常用命令
2.6、项目构建流程
2.7、设置文件(settings.gradle.kts)
2.8、构建脚本(build.gradle.kts)
Project 对象属性
插件部分
插件配置
application 插件,生成可执行程序
仓库管理
依赖管理
2.9、自定义任务
2.10、生命周期钩子
2.11、项目发布
2.12、创建 SpringBoot 项目
2.13、多项目配置
多项目目录结构
项目创建
依赖传递
统一配置
一、前置说明
Ps:如果不是因为某种必须原因,建议学习 Maven 即可,Gradle 的学习成本比 Maven 要高很多...
所需要具备的前置知识:
- 熟悉 SpringBoot
- 熟悉 Kotlin 语言.
- 熟悉 Maven 依赖管理
- 微服务(多项目配置会讲到)
二、Gradle 启动!
2.1、安装
a)安装之前,确保安装好 Java 环境,版本不能低于 Java 8(这种远古版本就别用了),本文使用 Java 17 .
b)进入 Gradle 官网下载 Gradle 8.5 版本(Gradle 版本兼容性很差,不同版本差异很大,不建议轻易更换),选择以编译好的 二进制 文件即可.
官网下载地址如下:
https://gradle.org/releases/?_gl=1*bycxul*_ga*MTkwMDMxNTMyMS4xNzAzNjkxNjA5*_ga_7W7NC6YNPT*MTcwMzc2MDE2OS4yLjEuMTcwMzc2MTE0OS4zNi4wLjA.
c)下载完后,解压,建议放到 C:/Program Files 目录下
d)配置环境变量:
e)打开命令窗口,输入 gradle -v 查看配置是否生效:
2.2、初始化项目
a)打开 cmd 窗口,执行以下命令来初始化项目:
gradle init
b)出现以下内容让我们初始化项目类型,选择 2 应用类型.
c)本文统一使用 Kotlin 语言讲解,选择 4 号:
d)是否生成多个子项目结果. 这里我们先以最简单的单体项目来进行讲解,选择 no 即可:
e)选择编写 gradle 脚本采用的语言,这里使用 Kotlin 语言(也是官方推荐的语言):
f)指定当前项目的名称以及包名,默认是当前目录的名字.
g)选择 Java 版本,这里使用 Java17,输入 17 即可.
h)是否选择使用新特性,选择 no 就可以了(gradle 的兼容性真的很差...),这样就完成了初始化.
Ps:不同版本的 Gradle 对 IDEA 版本同样存在兼容性的问题,推荐使用 IDEA 2023.3 或者更高的版本.
i)使用 IDEA 打开这个项目,打开后会进行初始化,报考 Gradle 当前版本,以及所需要的依赖包和 Kotlin 相关库.
但是我们本地不是已经安装 gradle 了么,为什么又要下载一次?
这是由于 gradle wrapper 的作用. 因为 gradle 的跨版本兼容性很差,所以她指定了当前项目使用的 gradle 版本,让不同开发人员或者 CI/CD 系统都能使用相同的 gradle 版本来构建项目. gradle wrapper 还有另外一个好处,它可以自动下载和使用正确版本的 gradle,无需手动安装或者配置 gradle,使得团队协作更加方便. 后续别人拿到这个项目的时候,不需要再系统中重新部署 gradle 环境.
如果初始化出现以下错误:
说明你之前配置过 gradle ,只需要去 file -> settings 中配置一下以下信息即可
2.3、gradle 项目目录介绍
- .gradle:Gradle自动生成的项目缓存目录。
- .idea:这个是IDEA的项目配置目录,跟Gradle生成的没关系,无视掉就行。
- app:存放整个项目的源代码、测试等,这里面就是我们写代码的地方了(使用 gradle 命的方式创建会出现此模块,如果使用 IDEA 创建,则不会出该现模块)。
- build.gradle.kts:项目的gradle构建脚本。
- src:存放源代码和测试代码。
- main:编写所有项目核心代码。
- test:编写项目测试代码。
- gradle:包含JAR文件和Gradle Wrapper的配置。
- gradlew:适用于macOS和Linux的使用Gradle Wrapper执行构建的脚本(这里的版本就是GradleWrapper指定的版本)
- gradlew.bat:适用于Windows的使用Gradle Wrapper执行构建的脚本。
- settings.gradle.kts:定义子项目列表的项目配置文件,也是最关键的设置文件。
gradle 在创建项目的时候给我们生成了一个主类用来测试:
class App {val greeting: Stringget() {return "Hello World!"}
}fun main() {println(App().greeting)
}
可以看到如下运行结果:
2.4、Gradle 项目下载慢?(万能解决办法)
腾讯云做的国内镜像:
https://mirrors.cloud.tencent.com/gradle/
a)解决 gradle 不同版本下载慢的问题:修改当前项目的 gradle/wrapper/gradle-wrapper.properties 文件,位置如下:
修改内容如下:
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
# 1.默认走如下地址,由于停止了国内的 CDN,下载速度特别慢
# distributionUrl=https\://services.gradle.org/distributions/gradle-8.5-bin.zip
# 2.因此,可以使用腾讯云提供的镜像,下载速度极快
distributionUrl=https\://mirrors.cloud.tencent.com/gradle/gradle-8.5-bin.zip
networkTimeout=10000
validateDistributionUrl=true
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
b)解决依赖包下载慢的问题:使用 阿里云 的镜像网站即可.
repositories {maven {setUrl("https://maven.aliyun.com/repository/public")}mavenLocal()mavenCentral()
}
2.5、Gradle 常用命令
gradle 的构建项目的命令就是通过前面我们讲到 gradle 初始化的项目中包含两个构建脚本实现的,分别是 gradle 和 gradle.bat,前者是 mac 系统适用,后者是 win 系统适用.
a)首先来看一下 gradle 支持的所有任务,可以通过以下命令来执行.
./gradlew.bat task
task 中包含了大量的命令操作,如下:
PS D:\codeRepositories\Gitee\java\gradle_test> .\gradlew.bat task
Downloading https://mirrors.cloud.tencent.com/gradle/gradle-8.5-bin.zip
............10%.............20%............30%.............40%.............50%............60%.............70%.............80%............90%.............100%
Starting a Gradle Daemon, 1 incompatible and 1 stopped Daemons could not be reused, use --status for details
Directory 'D:\JDK8' (Windows Registry) used for java installations does not exist
Directory 'D:\JDK8' (Windows Registry) used for java installations does not exist
<==
> Task :tasks------------------------------------------------------------
Tasks runnable from root project 'gradle_test'
------------------------------------------------------------Application tasks
-----------------
run - Runs this project as a JVM applicationBuild tasks
-----------
assemble - Assembles the outputs of this project.
build - Assembles and tests this project.
buildDependents - Assembles and tests this project and all projects that depend on it.
buildKotlinToolingMetadata - Build metadata json file containing information about the used Kotlin tooling
buildNeeded - Assembles and tests this project and all projects it depends on.
classes - Assembles main classes.
clean - Deletes the build directory.
jar - Assembles a jar archive containing the classes of the 'main' feature.
kotlinSourcesJar - Assembles a jar archive containing the sources of target 'kotlin'.
testClasses - Assembles test classes.Build Setup tasks
-----------------
init - Initializes a new Gradle build.
wrapper - Generates Gradle wrapper files.Distribution tasks
------------------
assembleDist - Assembles the main distributions
distTar - Bundles the project as a distribution.
distZip - Bundles the project as a distribution.
installDist - Installs the project as a distribution as-is.Documentation tasks
-------------------
javadoc - Generates Javadoc API documentation for the 'main' feature.Help tasks
----------
buildEnvironment - Displays all buildscript dependencies declared in root project 'gradle_test'.
dependencies - Displays all dependencies declared in root project 'gradle_test'.
dependencyInsight - Displays the insight into a specific dependency in root project 'gradle_test'.
help - Displays a help message.
javaToolchains - Displays the detected java toolchains.
kotlinDslAccessorsReport - Prints the Kotlin code for accessing the currently available project extensions and conventions.
outgoingVariants - Displays the outgoing variants of root project 'gradle_test'.
projects - Displays the sub-projects of root project 'gradle_test'.
properties - Displays the properties of root project 'gradle_test'.
resolvableConfigurations - Displays the configurations that can be resolved in root project 'gradle_test'.
tasks - Displays the tasks runnable from root project 'gradle_test' (some of the displayed tasks may belong to subprojects).Verification tasks
------------------
check - Runs all checks.
checkKotlinGradlePluginConfigurationErrors - Checks that Kotlin Gradle Plugin hasn't reported project configuration errors, failing otherwise. This task always runs before compileKotlin* or similar tasks.
test - Runs the test suite.To see all tasks and more detail, run gradlew tasks --allTo see more detail about a task, run gradlew help --task <task>BUILD SUCCESSFUL in 34s
1 actionable task: 1 executed
PS D:\codeRepositories\Gitee\java\gradle_test>
这里我们主要来看一下下图中的命令:
b)task 中的第一个 run 命令会自动编译和运行项目,拿出来单独执行,效果如下:
c)如果将来我们修改了项目的内容,需要重新编译,就要先进行 clean 进行清理
d)编写号 Java 项目之后,第一步就是编译成 class 文件
./gradlew classes
此时就会在 app 目录下生成一个 build 目录,此目录中就存在的是编译之后的文件了.
e)有些时候我们不想执行测试,只想构建整个项目,可以添加参数跳过:
./gradlew build -x test
f)但是这样敲命令太烦人了,IDEA 中已经包含了 Gradle 插件,可以直接使用:
2.6、项目构建流程
gradle 项目构建流程:
2.7、设置文件(settings.gradle.kts)
a)settings.gradle.kts 是整个 Gradle 项目的入口,用来定义所有子项目,让他们参与到构件中.
因此:
- 对于单个项目构建,settings.gradle.kts 是可选的.
- 对于多项目构建,settings.gradle.kts 文件必须存在,并配置定义所有的子项目.
b)settings.gradle.kts 文件中,gradle 会默认实例化一个 Settings 对象,所有项目声明都是通过她来实现的.
settings.rootProject.name = "demo1"
也可以省略掉 settings.
rootProject.name = "demo1"
c)Settings 对象
包含如下常用属性:
属性 | 描述 |
---|---|
buildCache | 项目构建所用缓存配置。 |
plugins | 用于设置的插件。 |
rootDir | 项目构建的根目录,根目录是整个项目目录最外层。 |
rootProject | 构建的根项目。 |
settings | 返回设置对象。 |
包含以下方法可以调用:
方法 | 描述 |
---|---|
include() | 将指定名称的项目添加到构建列表中。 |
includeBuild() | 添加指定路径上的其他Gradle项目到构建列表中。 |
d)一般 Gradle 设置文件按照如下方式编写:
// 当前项目的名称
rootProject.name = "demo1"//每个子模块的名称(没有子模块可以不写)
include("aaa")
include("bbb")
include("ccc")
e)配置文件中的内容,本质是对 Gradle API 方法的调用,结合 Kotlin 中 {...} 语法(Kotlin 中称为 lambda)
2.8、构建脚本(build.gradle.kts)
Project 对象属性
在每一个 build.gradle.kts 文件中,Gradle 都会为其创建一个 Project 实例对象,可以直接使用.
group = "com.cyk"
version = "1.0-SNAPSHOT"
当然,也可以省略 project
group = "com.cyk"
version = "1.0-SNAPSHOT"
此对象中,还包含以下常见属性
属性 | 类型 | 描述 |
---|---|---|
name | String | 项目目录的名称。 |
path | String | 该项目的完全限定名称。 |
description | String | 该项目的描述。 |
layout | ProjectLayout | 通过此对象来访问项目中的关键位置。 |
另外常用属性还有一些是以 lambda 的形式来编写的,往下走~
插件部分
plugins {kotlin("jvm") version "1.9.21"application
}//也可以写成以下形式
plugins {id("org.jetbrains.kotlin.jvm") version "1.9.21"id("application")
}
kotlin 表示整个项目的所使用的插件,而 application 是由官方内置的插件,可以不用指定 version ,而 kotlin 未被官方内置,所以需要手动指定 version ,Gradle 才能在仓库中找到她.
插件配置
另外还可以对这些插件进行一些配置,例如编译的目标版本是 jdk17
tasks.withType<KotlinCompile> {kotlinOptions.jvmTarget = "17"
}
application 插件,生成可执行程序
使用 application 插件,它包含 java 插件的全部功能,同样支持编译和打包,并且支持生成可执行的应用程序.
plugins {kotlin("jvm") version "1.9.21"application //引入 application 插件
}application {//配置主类(build.classes.kotlin 目录下的绝对路径)//注意: Main.kt 编译后生成的字节码文件名为 MainKt//指导生成可执行程序执行的入口mainClass.set("com.cyk.kt.MainKt")
}
通过 build 命令构建以后,可以看到 application 插件生效了,生成了如下文件:
这里我们只需要解压缩,就能看到 application 插件生成的可执行程序:
进入 bin 目录
双击运行 demo1.bat 即可运行(建议可以先打开终端,再打开该程序,否则程序一闪而过)
也可以直接通过 idea 提供的插件,直接运行可执行程序,如下
仓库管理
初始化 Gradle 项目之后,默认是选择 Maven 中央仓库,下载速度极慢(慢到即使有梯子也不行,因为 Gradle 关闭了国内的 cdn)
repositories {mavenCentral()
}
为了解决上述问题,我们一般都是优先使用本地仓库,本地仓库没有,再去阿里云仓库(速度快),最后在考虑中央仓库.
repositories {mavenLocal() //本地仓库maven {setUrl("https://maven.aliyun.com/repository/public") //阿里云仓库(第三方仓库)}mavenCentral() //中央仓库
}
依赖管理
a)这里可以使用以下函数导入依赖:
- implementation:导入依赖,用于编译和运行生产代码。
- testImplementation:导入依赖,用于编译和运行测试代码。
- runtimeOnly:仅在运行时可用,比如 MySQL 驱动这类我们不需要在项目中直接使用,但是在项目运行时有需要用到的依赖.
- api:与 implementation 类似,但是会暴露依赖项给项目所有模块(多项目配置中详解)
- compileOnly:表示导入的依赖只在编译时可用,编译完后不会将依赖打包.
- kapt:用于添加 Kotlin 注解处理器依赖项。
- annotationProcessor:用于添加 Java 注解处理器依赖项。
- androidTestImplementation:用于添加Android测试时需要的依赖项。
b)函数的参数就是一个字符串,就是我们依赖的组、名称、版本号:
org.junit:junit-bom:5.9.1
对应的组为org.junit
,依赖名称为:junit-bom
,版本号为:5.9.1
c)使用 implementation 添加依赖的步骤:
- 去 https://mvnrepository.com/ 找到所需要的包
- 直接复制粘贴到项目中
dependencies {testImplementation(kotlin("test"))implementation("org.springframework.boot:spring-boot-starter:2.6.7")
}
另外,还可以分开编写 组、名称、版本,提高可读性:
dependencies {testImplementation(kotlin("test"))implementation("org.springframework.boot", "spring-boot-starter","2.6.7")
}
在使用依赖时,我们可能需要排除某些不需要的依赖,或者与其他依赖冲突,我们也可以对依赖进行排除操作:
dependencies {testImplementation(kotlin("test"))implementation("org.springframework.boot", "spring-boot-starter","2.6.7") {//以 lambda 的形式排除依赖exclude("org.springframework.boot", "spring-boot-starter-logging")}
}
2.9、自定义任务
a)Gradle 上一个工作由多个任务来完成,比如构建、编译、清理... 这些任务都由插件提供.
不引入任何插件的情况下,只有一些内置任务:
b)引入 Kotlin / Java 插件之后,就出现了 编译、构建、打包... 等任务.
plugins {kotlin("jvm") version "1.9.21"application //引入 application 插件
}
c)如果觉得插件提供的任务不够,还可以在 build.gradle.kts 中自定义添加.
注册任务需要使用 register 或 create 函数来完成,例如如下:
tasks.register("hi~") {//第一个参数是任务名称,第二个参数是 lambda 编写的具体任务//任务包含一个完整的操作列表,需要传入对应的 Action 到队列中,这样便会依次执行doFirst { //向队列首部插入 Actionprintln("自定义任务开始!")}doLast { //向队列尾部插入 Actionprintln("自定义任务结束!")}
}
刷新之后就出现了我们自定义的任务
效果如下:
我们甚至还可以配置此任务所属的组,以及描述信息:
d)另外我们还可以指定自定义任务的前置任务,例如但我们点击自定义任务时,先执行 build 命令,如下:
tasks.register("hi~") {//第一个参数是任务名称,第二个参数是 lambda 编写的具体任务group = "build"description = "自定义任务~"//指定前置任务为 builddependsOn(tasks.build)doFirst { //向队列首部插入 Actionprintln("task start~")}doLast { //向队列尾部插入 Actionprintln("task end~")}
}
手动执行自定义任务后,自动先触发 build 命令
e)当然,返回来也可以,例如我们执行 build 命令时,会先自动执行自定义任务:
f)在 gradle 中,所有任务都是 Task 子类,除了上述所写方式(register),我们也可以自己创建 Task 子类,用来编写自定义任务类型:
//继承 DefaultTask 来创建一个自定义的 HiTask 类
//这个类要么是可继承,要么是 open,要么是抽象类
open class HiTask: DefaultTask() {private var name: String = ""fun user(name: String) {this.name = name}@TaskAction //添加@TaskAction 注解来声明此函数为任务fun hi() {println("${name}: 最帅!")}}//使用 register 来指明我们自定义的任务类型
tasks.register<HiTask>("hi") {this.user("cyk") //此时 this 就是 HiTask
}
效果如下:
g)Gradle 还提供了一些内置任务类型,例如复制任务:
tasks.register<Copy>("hello") { //这里使用Copy类型from("build/classes") //使用from和into设置复制的目录和目标位置into("test")dependsOn(tasks.build) //依赖一下build
}
2.10、生命周期钩子
有时候我们希望在 Gradle 整个声明周期中不同时期执行一些操作,就可以使用钩子函数(类似 Vue 钩子).
- 构建初始阶段
- gradle.settingsEvaluated() 完成项目的配置阶段之后调用(只能定义在 setting.gradle 或 init.gradle 脚本中)
- gradle.projectsLoaded() 所有项目加载之后调用(只能定义在 setting.gradle 或 init.gradle 脚本中)
- 配置阶段
- gradle.beforeProject() 每个项目完成配置之前调用(只能定义在 setting.gradle 或 init.gradle 脚本中)
- gradle.afterProject() 每个项目完成配置之后调用
- gradle.projectEvaluated() 所有项目全部完成配置之后调用
- gradle.afterEvaluate() 整个配置阶段完成后调用
- gradle.taskGraph.whenReady 全部任务图已经构建完成可以就绪后调用
- 执行阶段
- gradle.taskGraph.beforeTask 执行每一个任务之前调用
- gradle.taskGraph.afterTask 每一个任务执行完成之后调用
- gradle.buildFinished 整个构建全部结束后调用
例如,我们可以利用这个特性来统计某一个任务的耗时:
2.11、项目发布
我们可以将自己的 Gradle 项目发布到 Maven 仓库中,这里以发布到本地仓库为例:
publishing {publications {//Maven 坐标信息create<MavenPublication>("library") {groupId = "com.cyk"artifactId = "demo1"version = "0.0.1"from(components["java"]) // jar 包发布}}//指定发布仓库repositories {mavenLocal() //发布到本地 Maven 仓库}
}
执行 publish 命令即可发布到本地仓库(注意每次发布都更新一下版本号,防止仓库中优先执行缓存)
此时在 .m2 中就可以看到我们发布的项目了
2.12、创建 SpringBoot 项目
这里使用 IDEA 创建 Kotlin SpringBoot 项目就不用多说了... (注意选择 Gradle Kotlin DSL 即可)
这里来看一下项目自动生成的 build.gradle.kts 文件:
import org.jetbrains.kotlin.gradle.tasks.KotlinCompileplugins {id("org.springframework.boot") version "3.1.8" //SpringBoot 插件id("io.spring.dependency-management") version "1.1.4" //Spring 依赖管理插件kotlin("jvm") version "1.8.22"kotlin("plugin.spring") version "1.8.22"
}group = "com.cyk"
version = "0.0.1-SNAPSHOT"java {sourceCompatibility = JavaVersion.VERSION_17 //配置 Java 源代码编译版本
}// Maven 仓库配置
repositories {maven {setUrl("https://maven.aliyun.com/repository/public")}mavenLocal()mavenCentral()
}// 依赖配置
dependencies {implementation("org.springframework.boot:spring-boot-starter-web")implementation("com.fasterxml.jackson.module:jackson-module-kotlin")implementation("org.jetbrains.kotlin:kotlin-reflect")testImplementation("org.springframework.boot:spring-boot-starter-test")
}//对 Kotlin 编译任务进行配置(告诉 Gradle 中所有类型为 KotlinCompile 任务,然后进行配置)
tasks.withType<KotlinCompile> {//指定编译参数kotlinOptions {freeCompilerArgs += "-Xjsr305=strict" //JSR-305 是一组用于 Java 编程语言的注解,用于提供更多的静态代码分析信息jvmTarget = "17" //生成 JVM 字节码的目标版本}
}//让 Gradle 再执行测试时使用 Junit 平台
tasks.withType<Test> {useJUnitPlatform()
}
2.13、多项目配置
多项目目录结构
一般分布式项目,我们都会在一个项目中包含多个模块,不同模块负责不同功能.
这里我们来看一下,一般多模块的结构如下:
xxx-parent
|
├── user-service
│ ...
│ └── build.gradle.kts
├── album-service
│ ...
│ └── build.gradle.kts
└── settings.gradle.kts
settings.gradle.kts 用于全局配置,而 build.gradle.kts 用来对具体的模块进行配置.
项目创建
a)新建一个简单的 project
b)接着,就可以删除掉不需要的目录,比如: src 目录、build.gradle.kts、gradlew 等.
c)右键 gradle-parent ,然后创建子模块.
Ps:这里语言选择没有 Kotlin,也可以先使用 Java 创建
d)创建完后,可以看到最外层的 settings.gradle.kts 文件自动为我们添加了模块.
Ps:此时我们在根项目中执行任何命令,都会对全部子模块生效
e)由于创建模块时不支持指定 Kotlin 语言,因此我们先指定的 Java 语言.
这里就可以将 java 目录重命名为 kotlin
此时我们只需要随便创建一个 Kotlin 文件
他就会提示我们没有配置 Kotlin,点击配置后,IDEA 就会自动为我们配置 Kotlin 相关插件.
选择版本即可
依赖传递
a)有时候,我们需要在 子模块a 中引入 子模块b,我们就可以在项目中通过 implementation(project(":xxx")) 来引入其他子模块,如下:
b)gradle 项目通过 implementation 进行依赖传递存在这样一个问题:
例如有三个模块:a、b(依赖 a)、c(依赖b)
按照这个传递关系来说 c 是可以拿到 a 中的东西(Maven 是支持的),但实际上:
- b 能拿到 a 中的东西.
- c 能拿到 b 中的东西.
- 但是 c 不能拿到 a 中的东西.
也就是说通过 implementation 进行依赖传递,最多只能传递一层.
Ps:gradle 为什么要这样设定呢?因为这样编译时只需要处理一层,速度就会非常快,大部分情况下非常推荐使用 implementation 进行依赖导入.
但如果一定要是实现依赖传递的效果,也不是不行,只是需要使用另一个插件提供的方法来导入:
统一配置
有些时候,我可能每次创建一个子模块都要在 build.gradle.kts 中配置很多相同的配置,例如 仓库地址、插件.......
因此我们可以直接在项目根目录下创建一个 build.gradle.kts 文件来编写统一配置:
plugins {kotlin("jvm") version "1.8.22" apply false
}subprojects { //subprojects表示对所有的子项目生效apply(plugin = "kotlin")//定义插件需要使用apply来完成,plugin{}在这里不行repositories { //定义自定义仓库地址maven {setUrl("https://maven.aliyun.com/repository/public")}mavenLocal()mavenCentral()}
}
这样我们在子项目中就不用再配置相同的配置了.