Gradle+Groovy基礎篇
在Java專案中,有兩個主要的構建系統:Gradle和Maven。構建系統主要管理潛在的複雜依賴關係並正確編譯專案。還可以將已編譯的專案以及所有資源和原始檔打包到.war
或.jar
檔案中。對於簡單的構建,Maven和Gradle之間的選擇幾乎是個人喜好之一,或者也許是公司CTO或技術經理的偏好。他們倆都是非常好的構建工具。但是,對於更復雜的專案,Gradle比Maven更勝一籌。
Gradle構建的利與弊
個人喜歡Gradle;我討厭XML,複雜的Java/Groovy專案,如果沒有Gradle,幾乎是寸步難行的。除了沒有複雜的XML以外,Gradle還使用Groovy或Kotlin編寫的構建指令碼提供了靈活性和更快的構建速度。藉助Kotlin或Groovy的全部功能以及Gradle API庫,您可以建立功能強大且複雜的構建指令碼。這肯定是提升效率的工具。
對於DSL(特定於域的語言)需要一些時間來適應,並且Gradle以難以學習而著稱。但是,我認為這主要是因為人們已經習慣了Maven。使用Gradle,您實質上可以學習一種構建語言,而不只是簡單地學習XML。與僅在Maven中新增依賴項相比,充分利用Gradle無疑具有更陡峭的學習曲線。但是向Gradle檔案新增依賴項實際上並不比在Maven中困難。擴充套件和自定義Gradle構建比編寫Maven外掛和自定義構建步驟要簡單得多。
Gradle還極大地縮短了構建時間,尤其是在大型專案中,因為Gradle僅處理已更改的任務和檔案就可以很好地完成工作。此外,它提供了構建快取和構建守護程序,使重複構建的效能更高。而且,像Maven一樣,它使用並行執行緒進行依賴關係解析和專案構建。同樣,對於小型,簡單的構建,這種效能提升可能並不明顯。但是對於較大的專案,這種效能提升是巨大的。
因此,總結一下。Gradle是:
- 大型專案更快
- 無限制可定製
==
更陡峭的學習曲線 - 使用Groovy或Kotlin代替XML
而Maven是:
- 普遍採用
- 對於較小專案更簡單
- 帶有XML和尖括號
Groovy的優點
簡要介紹一下Groovy。Groovy是一種JVM語言,它可以編譯為與Java相同的位元組碼,並且可以與Java類無縫地互操作。Groovy是Java的向後相容超集,這意味著Groovy可以透明地與Java庫和程式碼互動。但是,它還增加了許多新功能:可選的鍵入,函數語言程式設計,執行時靈活性以及許多超程式設計內容。它還極大地清理了Java中許多冗長的程式碼格式。Groovy尚未成為主流的開發語言,但是它已經在測試(由於其簡化的語法和超程式設計功能)和構建系統中佔據了一席之地。
依存關係
您需要為本教程安裝一些內容:
Java:您可能已經安裝了Java。本教程至少需要Java 1.8。如果不是,請轉到官網下載並安裝它。
Gradle:但是,由於本教程是有關Gradle的教程,因此在本教程中,您可以繼續進行安裝。
認識build.gradle
build.gradle
檔案是Gradle專案的核心,是構建配置必不可少的一項。就比如pom.xml
對於Maven來說,這是等效的(沒有所有令人討厭的尖括號)
讓我們來看一個。
// 配置執行構建指令碼的要求
buildscript {
// 設定自定義屬性
ext {
springBootVersion = '2.1.6.RELEASE'
}
// 解決buildscript塊中的依賴項時,檢查Maven Central中的依賴項
repositories {
mavenCentral()
}
// 我們需要spring boot外掛來執行構建指令碼
dependencies {
classpath("org.springframework.boot:spring-boot-gradle-plugin:${springBootVersion}")
}
}
// 新增構建外掛
apply plugin: 'java'
apply plugin: 'org.springframework.boot'
apply plugin: 'io.spring.dependency-management'
// 設定全域性變數
group = 'com.okta.springboottokenauth'
version = '0.0.1-SNAPSHOT'
sourceCompatibility = 1.8
// 用於搜尋以解決專案依賴關係的倉庫地址
repositories {
mavenCentral()
}
// 專案依賴
dependencies {
implementation( 'com.okta.spring:okta-spring-boot-starter:1.2.1' )
implementation('org.springframework.boot:spring-boot-starter-security')
implementation('org.springframework.boot:spring-boot-starter-web')
testImplementation('org.springframework.boot:spring-boot-starter-test')
testImplementation('org.springframework.security:spring-security-test')
}
理解Gradle構建檔案的關鍵是要意識到它是一個指令碼,內建在Groovy DSL中。粗略地講,它是一個配置指令碼,它呼叫定義了配置選項的一系列閉包(考慮函式)。它看起來像JSON或propertiy檔案,儘管從技術上來說這是錯誤的。
但是,真正的有趣的來自build.gradle
Groovy指令碼。因為它可以執行任意程式碼並訪問任何Java庫,特定於構建的Gradle DSL和Gradle API。
Gradlebuildscript
讓我們從上至下檢視指令碼:
buildscript
閉包配置構建指令碼本身(與應用程式相對)所需的屬性,依賴項和源倉庫。接下來,
apply plugin
以非常好友的方式應用了外掛。這些擴充套件了Gradle-Groovy DSL框架的基本功能:將該java外掛與Spring Boot和Spring依賴項管理一起應用。Java外掛提供配置Gradle的期望標準的Java專案的目錄結構:src/main/java
,src/main/resources
,src/test/java
等,這些可以被配置為改變預設的目錄或新增新的目錄。接下來,將一些標準屬性應用於構建。
repositories
塊定義了構建指令碼將在哪裡尋找依賴關係。Maven Central是最常見的(mavenCentral()
),但也可以配置其他倉庫,包括自定義倉庫和本地倉庫。可以使用來將本地Maven快取配置為倉庫mavenLocal()
。如果團隊希望協調專案之間的構建,但又不想將專案構建檔案實際捆綁在一起,這將很有幫助。最後,定義專案依賴項。
其中每個模組定義閉包的順序無關緊要,因為大多數build.gradle
檔案僅定義依賴項,設定專案屬性並使用預定義的任務,因此檔案中元素的順序無關緊要。例如,沒有理由repositories
塊必須走在該dependencies
塊之前。您可以將build.gradle
檔案視為Gradle在執行呼叫它的shell命令分配的任何任務之前讀取的配置檔案。
但是,當您開始使用Gradle的功能來定義自定義任務並執行任意程式碼時,它將變得更加複雜。Gradle將以build.gradle
自上而下的方式讀取檔案,並執行在其中找到的所有程式碼塊;根據此程式碼的作用,它可以在指令碼中建立強制排序。此外,當您定義自定義任務和屬性(在Gradle API中找不到)時,排序很重要,因為這些符號不會被預先定義,因此必須在構建指令碼中定義它們才能使用它們。
什麼是閉包
回到Groovy剛問世時,函數語言程式設計是相當小眾的領域,將諸如閉包之類的東西帶入JVM感覺很瘋狂。如今,它變得更加普遍:Javascript中的每個函式都是閉包。一般來說,閉包是具有範圍的一流函式。
這意味著兩件事:
- 閉包是可以在執行時作為變數傳遞的函式
- 閉包保留對定義它們的變數範圍的訪問
Java版本的閉包稱為lambda。這些是在1.8版中引入Java的,順便說一句,這並不是在Groovy獲得最初的流行和函數語言程式設計開始發展的同時發生的。
為了演示lambda,請看一下名為的JUnit測試LambdaTest.java
。
src/test/java/com/okta/springboottokenauth/LambdaTest.java
interface SimpleLambda {
public int sum(int x, int y);
}
public class LambdaTest {
// 建立一個lambda函式
public SimpleLambda getTheLambda(int offset) {
int scopedVar = offset;
return (int x, int y) -> x + y + scopedVar;
}
@Test
public void testClosure() {
// 測試lambda方法,當offset=1
SimpleLambda lambda1 = getTheLambda(1);
assertEquals(lambda1.sum(2,2), 5);
// 測試lambda方法,當offset=2
SimpleLambda lambda2 = getTheLambda(2);
assertEquals(lambda2.sum(2,2), 6);
}
}
這個示例很有代表性,演示了lambda的兩個基本屬性。在閉包或lambda函式中,實現是在getTheLambda(int offset)
方法中定義的。建立lambda時,將offset變數封裝在閉包範圍中並返回。該lambda被分配給變數。可以重複呼叫它,並且它將引用相同的作用域。此外,可以使用封裝在單獨作用域中並分配給其他變數的新變數來建立新的lambda。
來自強大的面向物件的背景,封閉最初感覺就像蟲洞在嚴格的物件範圍連續體上打穿透孔一樣,奇怪地將物件的各個部分在空間和時間上連線在一起。
Gradle只是閉包
採取build.gradle
檔案的依賴項部分:
dependencies {
implementation( 'com.okta.spring:okta-spring-boot-starter:1.2.1' )
implementation('org.springframework.boot:spring-boot-starter-security')
...
}
沒有Groovy DSL速記,實際上是:
project.dependencies({
implementation( 'com.okta.spring:okta-spring-boot-starter:1.2.1' )
implementation('org.springframework.boot:spring-boot-starter-security')
...
})
括號中的所有內容實際上都是傳遞給該project.dependencies()
方法的閉包。該project
物件是Project
該類的例項,該類是構建的主要API父類。
如您所見,這些函式將一系列依賴項作為字串傳遞。那麼,為什麼不使用更傳統的靜態資料結構(如JSON,屬性或XML)呢?原因是這些過載函式也可以使用閉包程式碼塊,因此可以進行深度自定義。
探索Gradle依賴項配置
依賴關係塊內部是一系列配置和名稱。
dependencies {
configurationName dependencyNotation
}
我們的build.gradle
檔案使用兩種配置:implementation
和testImplementation
。
implementation()
定義編譯時所需的依賴項。此配置方法稱為compile
。testImplementation()
並定義了僅用於測試(舊testCompile
)所需的依賴項。
您可能會看到的另一個依賴項配置是runtimeOnly
和testRuntimeOnly
。這聲明瞭執行時提供的不需要對其進行編譯的依賴項。
定義依賴關係的方法比對本文的範圍有用的方法更多。幾乎可以說任何東西都可以是依賴項:本地檔案,jar的目錄,另一個Gradle專案等等,並且可以將依賴項配置為執行某些操作,例如排除某些子依賴項。
值得注意的是:Gradle和Maven以完全相同的方式解決依賴關係。例如,假設我們想從Spring Boot Starter
中排除Log4j
依賴關係,我們可以這樣做:
dependencies {
implementation( 'com.okta.spring:okta-spring-boot-starter:1.2.1' ) {
exclude group: 'org.apache.logging.log4j', module: 'log4j-api'
}
}
或者說我們想將目錄中的所有檔案都包含libs
為依賴項:
dependencies {
implementation fileTree('libs')
}
打包Gradle版本
關於Gradle的一件很棒的事情是Gradle包裝器。Gradle命令列為gradle
。但是,您會注意到在網上的許多地方,您都會看到./gradlew
或gradlew.bat
。這些是呼叫包裝程式的命令。
包裝器允許專案捆綁在專案本身內部構建專案所需的Gradle版本。這樣可以確保對Gradle的更改不會中斷構建。它還可以確保即使沒有安裝Gradle的人也可以執行構建。
它將以下檔案新增到您的專案:
├── gradle
│ └── wrapper
│ ├── gradle-wrapper.jar
│ └── gradle-wrapper.properties
├── gradlew
└── gradlew.bat
gradlew
和gradlew.bat
是用於Linux/OSX和Window(分別)執行指令碼。他們執行build.gradle
使用捆綁的搖籃檔案.jar
的gradle/wrapper
子目錄。
任務
任務是Gradle的核心。Java外掛增加了十幾個任務,包括:clean
,compile
,test
,jar
,和uploadArchives
。Spring Boot外掛添加了bootRun
任務,該任務執行Spring Boot應用程式。
通常,任務是這樣執行的:gradle taskName otherTaskName
,或使用包裝器:./gradlew taskName otherTaskName
。
如果開啟終端並cd進入示例專案的基本目錄,則可以使用gradle tasks
列出build.gradle
檔案定義的所有任務。tasks
當然,它本身是由基本Gradle API定義的任務。
> Task :tasks
------------------------------------------------------------
Tasks runnable from root project
------------------------------------------------------------
Build 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.
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 main classes.
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
assembleMonitorDist - Assembles the monitor distributions
distTar - Bundles the project as a distribution.
distZip - Bundles the project as a distribution.
installDist - Installs the project as a distribution as-is.
installMonitorDist - Installs the project as a distribution as-is.
monitorDistTar - Bundles the project as a distribution.
monitorDistZip - Bundles the project as a distribution.
Documentation tasks
-------------------
groovydoc - Generates Groovydoc API documentation for the main source code.
javadoc - Generates Javadoc API documentation for the main source code.
Help tasks
----------
buildEnvironment - Displays all buildscript dependencies declared in root project 'fun'.
components - Displays the components produced by root project 'fun'. [incubating]
dependencies - Displays all dependencies declared in root project 'fun'.
dependencyInsight - Displays the insight into a specific dependency in root project 'fun'.
dependentComponents - Displays the dependent components of components in root project 'fun'. [incubating]
help - Displays a help message.
model - Displays the configuration model of root project 'fun'. [incubating]
projects - Displays the sub-projects of root project 'fun'.
properties - Displays the properties of root project 'fun'.
tasks - Displays the tasks runnable from root project 'fun'.
IDE tasks
---------
cleanIdea - Cleans IDEA project files (IML, IPR)
idea - Generates IDEA project files (IML, IPR, IWS)
openIdea - Opens the IDEA project
Verification tasks
------------------
check - Runs all checks.
test - Runs the unit tests.
Rules
-----
Pattern: clean<TaskName>: Cleans the output files of a task.
Pattern: build<ConfigurationName>: Assembles the artifacts of a configuration.
Pattern: upload<ConfigurationName>: Assembles and uploads the artifacts belonging to a configuration.
To see all tasks and more detail, run gradle tasks --all
To see more detail about a task, run gradle help --task <task>
我想指出dependencies
任務。它將列出一棵樹,其中包含專案所需的所有依賴關係(包括子依賴關係)。嘗試gradle dependencies
在專案根目錄中執行。您可以使用該dependencyInsight
任務來深入瞭解特定的子依賴項。
另一個有助於解決問題的properties
任務是該任務,該任務列出了在根專案物件例項上定義的所有屬性。
當然,在開發Spring Boot專案時,可以使用命令:./gradlew bootJar
,該任務將專案及其依賴項打包在一個jar檔案中。
到此,基礎篇完事兒,提高篇中將會實踐一下自定義任務和Groovy閉包在Gradle配置檔案build.gradle
檔案中如何使用。
- 鄭重宣告:文章禁止第三方(騰訊雲除外)轉載、發表,事情原委測試窩,首頁抄我七篇原創還拉黑,你們的良心不會痛嗎?
技術類文章精選
- java一行程式碼列印心形
- Linux效能監控軟體netdata中文漢化版
- 介面測試程式碼覆蓋率(jacoco)方案分享
- 效能測試框架第二版
- 如何在Linux命令列介面愉快進行效能測試
- 圖解HTTP腦圖
- 將swagger文件自動變成測試程式碼
- 五行程式碼構建靜態部落格
- 基於java的直線型介面測試框架初探
非技術文章精選
- 為什麼選擇軟體測試作為職業道路?
- 寫給所有人的程式設計思維
- 成為優秀自動化測試工程師的7個步驟
- 成為自動化測試的7種技能
- 自動化測試生命週期
- 如何在DevOps引入自動化測試
- Web端自動化測試失敗原因彙總
- 如何在DevOps引入自動化測試
- 測試人員如何成為變革的推動者
- 編寫測試用例的技巧