本來沒有想了解Gradle,但是在想看SpringBoot源碼的時候發現,在SpringBoot2.2.8版本之后,不再使用maven進行構建,而是使用Gradle。想著把SpringBoot源碼導入idea學習下源碼,但是來來回回折騰了好幾回,都是報錯,想著不如學習下Gradle。
Gradle的官方介紹:
Gradle 是一種廣泛使用且成熟的工具,擁有活躍的社區和強大的開發人員生態系統。
- Gradle 是 JVM 最常用的構建系統,也是 Android 和 Kotlin 多平臺項目的默認系統。 它擁有豐富的社區插件生態系統。
- Gradle 可以使用其內置功能、第三方插件或自定義構建邏輯來自動化各種軟件構建場景。
- Gradle 提供了一種高級、聲明性且富有表現力的構建語言,使您可以輕松讀取和編寫構建邏輯。
- Gradle 速度快、可擴展,可以構建任何規模和復雜程度的項目。
- Gradle 可產生可靠的結果,同時受益于增量構建、構建緩存和并行執行等優化。
我簡單的認知:可以用來管理項目需要的依賴,構建項目。
基本概念
Projects(項目):
就是整個項目工程,可以包含多個模塊或者單模塊的一個項目工程。Build Scripts(構建腳本):
是一個腳本文件,寫一些代碼來規定如何構建項目。Dependency Management(依賴關系管理):
管理項目結構和jar包的。Tasks(任務):
任務是gradle的基本工作單元,在構建腳本中可以包含任意個工作單元,類似于一個java類中的方法,可以隨意創建和定義,構建項目也像是一個個任務的執行。Plugins(插件):
類似于java中的引包,引入插件,就可以在腳本中使用這個插件提供的方法。Gradle項目結構
project├── gradle 1??
│ ├── libs.versions.toml 2??
│ └── wrapper 3??
│ ├── gradle-wrapper.jar 4??
│ └── gradle-wrapper.properties 5??
├── gradlew
├── gradlew.bat
├── settings.gradle(.kts) 6??
├── subproject-a
│ ├── build.gradle(.kts) 7??
│ └── src
└── subproject-b
├── build.gradle(.kts) └── src
- 用于存儲包裝器文件等的 Gradle 目錄
- 可以用來規定整個項目工程中的插件的版本
- 只是個目錄
- 項目運行所需要的標準gradle安裝包,為不同的用戶和環境可以配置相同的gradle安裝包,建議使用。
- 指定第四項中的包可以去哪里下載,可以指定本地地址,也可以使用鏡像地址,還可以配置一些和安裝包有關的配置。
- Gradle 設置文件,用于定義根項目名稱和子項目等等,就相當于maven項目中跟項目的pom.xml
- 子項目的構建腳本
多項目構建
多項目構建有兩種: * 使用 buildSrc目錄 的多項目構建: buildSrc目錄放在根目錄下一層中,也就是和根項目的子項目同層級。(SpringBoot源碼就是用的這種方式)* 復合構建: 官方文檔中描述的:// <font style="color:rgb(2, 48, 58);">最適合在 builds(</font>_<font style="color:rgb(2, 48, 58);">不是子項目</font>_<font style="color:rgb(2, 48, 58);">)之間共享 logic 或隔離對共享 build logic(即約定插件)的訪問。</font>
構建順序
1. 初始化 1. 檢測settings.gradle文件 2. 創建Settings實例 3. 確定需要構建哪些模塊(所以會在settings.gradle使用include標明有哪些模塊) 4. 為每一個模塊創建一個Project實例 2. 配置 1. 檢測每個模塊,也就是每個子項目中的build.gradle文件 2. 為請求的任務(就是task)創建任務圖 3. 執行任務 1. 分析任務圖的依賴關系 2. 執行任務Settings.gradle文件(只有根目錄會有)
```plain // 管理插件的 pluginManagement { // 這里定義的plugins只是為了限定版本號,并不會實際引入插件,還需要子項目的build.gradle中引入實際的plugin 但是不需要加上版本號了 // 配置插件下載的倉庫地址 repositories { maven { url 'https://maven.aliyun.com/repository/gradle-plugin' } maven { url 'https://plugins.gradle.org/m2/' } mavenCentral() gradlePluginPortal() } // 可以對某個插件做特殊處理 resolutionStrategy { eachPlugin { if (requested.id.id == "org.jetbrains.kotlin.jvm") { useVersion "${kotlinVersion}" } if (requested.id.id == "org.jetbrains.kotlin.plugin.spring") { useVersion "${kotlinVersion}" } } } }// 引入插件
plugins {
id “com.gradle.develocity” version “3.17.2”
id “io.spring.ge.conventions” version “0.0.17”
}
// 配置project實例的name屬性,可以直接點擊rootProject跳轉到java類中,就可以查看可以配置哪些屬性
rootProject.name=“spring-boot-build”
// 項目加載完需要執行的回調
settings.gradle.projectsLoaded {
develocity {
buildScan {
def toolchainVersion = settings.gradle.rootProject.findProperty(‘toolchainVersion’)
if (toolchainVersion != null) {
value(‘Toolchain version’, toolchainVersion)
tag(“JDK-KaTeX parse error: Expected 'EOF', got '}' at position 23: …inVersion") }? def buildDi…{scan.buildScanUri}|build scan>\n”
}
}
}
}
// 標明有哪些模塊
include “spring-boot-project:spring-boot-dependencies”
<h2 id="f8DHM">根目錄的build.gradle</h2>
```plain
buildscript {
// 規定了所有模塊中的build.gradle中需要用到的任務或者依賴,就到下面倉庫中,只針對構建腳本repositories {maven { url 'https://maven.aliyun.com/repository/central' }maven { url 'https://maven.aliyun.com/repository/public' }maven {url 'https://maven.aliyun.com/repository/apache-snapshots'}mavenLocal()mavenCentral()}dependencies {// 到上面指定的倉庫去找這個依賴classpath("io.spring.javaformat:spring-javaformat-gradle-plugin:0.0.15")}
}// 指定插件
plugins {id "base"// apply 默認是true, 表示自動開啟,也可以配置為false,根據條件開啟id "org.jetbrains.kotlin.jvm" apply false // https://youtrack.jetbrains.com/issue/KT-30276id "io.spring.nohttp" version "0.0.11"
}allprojects {// 設置了所有子項目都屬于 org.springframework.boot 分組group "org.springframework.boot"// 定義了多個Maven倉庫,項目實際代碼中需要的依賴都到下面幾個倉庫去下載repositories {maven {url 'https://maven.aliyun.com/repository/public/'}maven {url 'https://maven.aliyun.com/repository/central'}mavenLocal()mavenCentral()}configurations.all {resolutionStrategy.cacheChangingModulesFor 0, "minutes"}
}// 找到名為checkstyleNohttp 任務并且配置maxHeapSize屬性
tasks.named("checkstyleNohttp").configure {maxHeapSize = "1536m"
}
// 添加一個任務
task.register("one") {
}
模塊中的build.gradle
// 標明當前模塊需要哪些依賴,類似于pom文件
// 這里省略了版本號, 是因為在 spring-boot-dependencies中使用library方法規定了版本
// 類似于maven項目中專門用來放依賴的子項目,在這個pom文件已經指定了版本號,所以引用了這個項目的模塊不需要額外寫明版本號
dependencies {// api 編譯和運行時都需要的依賴項,并包含在已發布的 API 中implementation 'org.springframework.boot:spring-boot-starter-web' // 編譯和運行時都需要的依賴項api("org.springframework:spring-core")compileOnly 'org.projectlombok:lombok' // 僅編譯所需的依賴項,不包含在 runtime 或發布中runtimeOnly 'com.mysql:mysql-connector-j' // 僅在運行時需要的依賴項,不包含在 compile Classpath 中annotationProcessor 'org.projectlombok:lombok' // 用于編譯時注解處理的工具,它可以在編譯時期處理注解,生成額外的代碼testImplementation 'org.springframework.boot:spring-boot-starter-test' // 編譯和運行測試所需的依賴項。testRuntimeOnly 'org.junit.platform:junit-platform-launcher' // 僅運行測試所需的依賴項
}
api 編譯和運行時都需要的依賴項,并包含在已發布的 API 中。
implementation 編譯和運行時都需要的依賴項。
compileOnly 僅編譯所需的依賴項,不包含在 runtime 或發布中。
compileOnlyApi 依賴項僅需要用于編譯,但包含在已發布的 API 中。
runtimeOnly 僅在運行時需要的依賴項,不包含在 compile Classpath 中。
testImplementation 編譯和運行測試所需的依賴項。
testCompileOnly 僅測試編譯所需的依賴項。
testRuntimeOnly 僅運行測試所需的依賴項。// 將properties 寫入到這個目錄中的springBootVersion文件中
sourceSets {main {java {srcDirs syncJavaTemplates}}test {output.dir(tomcatConfigProperties, builtBy: "extractTomcatConfigProperties")}
}//
def syncJavaTemplates = tasks.register("syncJavaTemplates", Sync) {from("src/main/javaTemplates")into("build/generated-sources/main")def properties = ["springBootVersion": project.version]expand(properties)inputs.properties(properties)
}