Gradle快速上手——從Maven到Gradle
【本文寫作於2018年7月5日】
本文適合於有一定Maven應用基礎,想快速上手Gradle的讀者。
背景
Maven、Gradle都是著名的依賴管理及自動構建工具。提到依賴管理與自動構建,其重要性在當今軟件環境下不言而喻,Maven也是紅極一時。
Maven采用約定大於配置的思想,約定了工程結構,生命周期,采用嚴謹的XML格式進行構建腳本編寫,顯著地提升了軟件構建的效率。但當軟件越來越復雜後,大家突然發現Maven的腳本編制已然成了另外一個麻煩。絕大部分的使用者會掉入Maven的plugin陷阱——當你想做任何一件事,首先想到的是“能使用什麽插件?”接下來,就是在海量的插件中不斷尋找,甄選,終於找到了一個,打開文檔,學習插件所關聯的生命周期,在合適位置進行配置,編寫腳本。更可怕的問題是,在Maven中,Everything is plugin。即使一個非常簡單的操作,也需要尋找對應的插件,完成繁復的配置。插件使用較多時,插件之間還非常容易出現沖突,對某個操作,每個插件關聯的構建時機不同,配置上還需要很多技巧。久而久之,Maven的腳本構建,自身就可以寫出一本厚厚的書,而對於腳本的編寫者——開發人員——來說,為了完成一個自動化的動作所付出的努力有可能都會超過軟件本身,這不就是倒退嗎?
為了解決這個問題,Gradle橫空出世。Gradle使用Groovy語言,抽象出一套DSL,用於編寫構建腳本。腳本風格與程序類似,非常符合開發人員的口味,腳本復雜度相比於XML而言,得到了極大的簡化此外,Gradle在構建效率,操作便捷性上也比Maven有了較大的提高,因此越來越多的人開始倒向Gradle。
目前的Gradle最新版本已經到達5.0,但還沒有釋放正式版,最新的穩定版本是4.8.1。Gradle已經可以支持Java, C++, Python 以及多種主流語言,Gradle也是Google推薦的Android構建平臺。
本文使用的軟件版本
Gradle 4.8.1
Maven 3.2.2
Eclipse Photon Release (4.8.0)
JDK 1.8 Update 92 64bit
本文講解基於操作系統Windows 10,開發一個Java應用程序。
Gradle安裝
Gradle需要JDK1.7及以上版本,請自行準備。
保證JAVA_HOME,以及JAVA_HOME的bin目錄已經配置在操作系統的path中。
Gradle安裝非常簡單,官方也提供了多種安裝方式,所有主流系統的包管理器都可以使用。官方說明地址(https://gradle.org/install/)
不過對於長期混跡於Maven的老鳥來說,手動安裝是了解一門新技術的好方法。
從:
https://downloads.gradle.org/distributions/gradle-4.8.1-bin.zip
下載Gradle 4.8.1的二進制包。
下載後解壓至本地。
本例中,將之解壓至D:\DevEnv\gradle-4.8.1,同時,也將完整二進制包“gradle-4.8.1-bin.zip ”也放到了這個目錄中(後面有用)。
接下來,需要為Gradle創建一個用戶目錄,這個概念跟Maven一樣(Maven默認在當前用戶目錄中創建.m2文件夾,就是用戶目錄)。
本例中,我們在D:\DevEnv中創建了一個用戶目錄gradle_user_home,這個目錄會存放Gradle本地的配置,Wrapper,下載的庫文件等等。
接下來在系統變量中,配置好GRADLE_HOME及GRADLE_USER_HOME環境變量。
同時,也請確認本機的Maven(如果有),也配置了M2_HOME環境變量。
接下來,配置path變量,添加%GRADLE_HOME%\bin。
接下來,驗證安裝,啟動任意終端。運行 gradle -verion,顯示類似下面內容即為成功。
使用Gradle創建一個工程
Gradle對工程結構的約定與Maven相同,對於java工程,代碼保存在src/main/java,資源保存在src/main/resources。同樣測試代碼保存在src/test/java,測試資源src/test/resources。
Gradle不同於Maven的地方在於,一旦工程不是如約定的結構,Gradle經過簡單配置即可兼容,但對於Maven,多源碼文件結構是不被允許的。
本例演示創建一個VerifyCodeAPI的Java工程(最終可獨立運行),首先建立VerifyCodeAPI文件夾,接下來,VerifyCodeAPI工程根目錄下,執行gradle init --type "java-application",完成工程初始化。
註釋:gradle init 還可以創建很多類型的初始化工程,可以參考 https://docs.gradle.org/4.8/userguide/build_init_plugin.html?_ga=2.5247931.945099620.1530760557-568871993.1530760557#sec:build_init_types
初始化完畢後,目錄文件如下,可見gradle為工程建立了.gradle,gradle,build.gradle,gradlew,settings.gradle幾個文件。
初始化過程,實際上是創建gradle wrapper的過程,gradlew就是gradle wrapper的縮寫。有了gradle,為什麽還要創建一個wrapper?
gradle是一款構建工具,其自身也存在多個版本,每個版本也存在著差異。每個項目使用一個特定的gradle版本,項目組也只能保證自動構建在指定的版本下運作正常。在實際開發時,項目與項目使用的Gradle版本很有可能不同,如果同時使用兩個Gradle版本不同的項目怎麽辦?gradlew就是搞定這個問題來的。gradlew將本項目使用的gradle版本信息固化下來,保存在工程中,這些信息隨著代碼控制(Git、SVN等等)保存。使用了gradle wrapper後,每次構建項目使用gradlew命令行,而不是直接使用安裝在系統中的gradle,如果本地沒有gradlew中記錄的gradle版本,gradlew會自動下載,這樣的設計,可以保證在不同環境下,某一個項目使用特定版本的gradle進行編譯。
Gradle生成的文件及作用如下:
1 工程配置腳本。
2 Gradle Wrapper的可執行 JAR包。
3 Gradle Wrapper配置properties文件。
4 Gradle Wrapper供Linux等類Unix系統使用的腳本
5 Gradle Wrapper供Windows使用的腳本
6 配置構建包含的工程的文件(多工程,多模塊統一構建使用)
至此,工程創建完畢。
配置工程
接下來進行工程配置,最基本的,設置編碼,JDK版本,配置工程依賴庫。這部分都在build.gradle中完成。
本例配置如下:
buildscript { ext { springBootVersion = ‘2.0.3.RELEASE‘ } repositories { /* maven { url "https://plugins.gradle.org/m2/" } */ maven { url ‘http://maven.aliyun.com/nexus/content/groups/public/‘ } //mavenCentral() } 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 = "dreamstudio.ai.verifyCode.api" version = "3.0" description = "VerifyCode API Application" archivesBaseName = ‘VerifyCode_API‘ sourceCompatibility = 1.8 targetCompatibility = 1.8 tasks.withType(JavaCompile) { options.encoding = ‘UTF-8‘ } // java編譯的時候缺省狀態下會因為中文字符而失敗 [compileJava,compileTestJava,javadoc]*.options*.encoding = ‘UTF-8‘ repositories { mavenLocal() maven { url ‘http://maven.aliyun.com/nexus/content/groups/public/‘ } mavenCentral() } bootJar { baseName = ‘verifyCode-api‘ version = version } //配置依賴 dependencies { implementation ‘org.springframework.boot:spring-boot-starter-web‘ implementation( "net.sourceforge.tess4j:tess4j:4.0.2" ) implementation group: ‘commons-codec‘, name: ‘commons-codec‘, version: ‘1.11‘ }
下面對關鍵部分做以介紹:
1 buildscript。用於執行構建的腳本。gradle支持插件,這部分主要用於聲明構建本工程使用的插件,本例中在dependencies部分聲明的就是本工程依賴的插件。ext部分定義了一個變量,是插件版本,供下文引用。repositories標簽中聲明了這些插件的下載地址。本例中使用了阿裏雲的Maven庫下載構建插件。
2 apply plugin。聲明本工程使用的插件。這類插件通常包含了若幹的Task,與Maven類似。本例中java,就是gradle提供的基本插件之一,包含了構建一個java工程常規的task,如編譯類,測試,打包,執行,清理等等。
gradle還提供c++,groovy,java web,scala等基本插件,其他工程類型可以自行引入第三方插件,如Android Plugin。
3 工程基本描述。group = "dreamstudio.ai.verifyCode.api",等同於maven的的groupId,version = "3.0" 版本,
description = "VerifyCode API Application"描述,archivesBaseName = ‘VerifyCode_API‘工程打包文件名前綴。
4 JDK版本配置。sourceCompatibility = 1.8 源碼版本1.8,targetCompatibility = 1.8編譯目標版本1.8。
5 源碼編碼設置。
tasks.withType(JavaCompile) { options.encoding = ‘UTF-8‘ } // java編譯的時候缺省狀態下會因為中文字符而失敗 [compileJava,compileTestJava,javadoc]*.options*.encoding = ‘UTF-8‘
保證編碼都是UTF-8
6 依賴庫倉庫位置。repositories中聲明了本工程依賴的包的倉庫地址。Gradle可以使用多種類型的倉庫。mavenLocal()表示使用本地Maven倉庫(如果配置了環境變量,Gradle會從M2_HOME指向本地Maven安裝路徑中的conf\settings.xml中localRepository查找本地倉庫),maven {url ‘http://maven.aliyun.com/nexus/content/groups/public/‘} 表示使用阿裏雲Maven庫,mavenCentral()表示使用maven中央倉庫。
gradle查找包的時候,會按照聲明順序,由上至下進行查找。
註意:對於本地maven庫,gradle只會利用,當有不齊全的包時,gradle會下載,但不會存入本地maven庫,而是存放在gradle的USER_HOME下的caches目錄。
7 本工程依賴包聲明。dependencies中聲明本工程依賴。基本原理和Maven相同,寫法比maven極大簡化。
implementation( "net.sourceforge.tess4j:tess4j:4.0.2" ) implementation group: ‘commons-codec‘, name: ‘commons-codec‘, version: ‘1.11‘
以上是兩種寫法,第一種和第二種等價。gradle中,group等同於maven的groupId,name等同於artifactId。
運行構建
工程配置完畢後,就可以進行項目開發,關於如何使用IDE進行Gradle的工程開發,將在其他文章中介紹。本例中假定已經完成開發。接下來,演示工程構建效果。
在工程根路徑中,執行gradlew TASK名稱 TASK名稱 ... 可以執行構建的各個Task,執行某個Task時,其依賴的Task也會執行,這點與Maven類似,Gradle對構建進行了很多優化,可以自動檢測工程的變化,只執行必要的構建,構建速度相比Maven提升較大。
本例中使用gradlew clean bootJar 執行了清理,以及構建可獨立運行JAR的工作(bootJar Task是SpringBoot Gradle Plugin 提供,並不是標準java插件自帶)。
構建完畢的文件,會輸出到工程的build文件夾下。本例中libs中,就是最終可獨立運行的文件。
小結
經過上述過程,相信熟悉Maven的同學已經可以獨立搭建起Gradle運行環境,利用好目前搭建的Maven的倉庫,並且完成一個獨立的Java工程的創建(或者將已有工程改造成為Gradle工程)以及編譯打包。
本文旨在快速上手,並沒有關註Gradle的使用細節,關於Gradle使用的開發環境搭建,多工程、組件依賴,聯合打包等等技巧將在其他文章中介紹。
Gradle快速上手——從Maven到Gradle