Java中的Gradle與Groovy的區(qū)別及存在的關(guān)系
前言:
在Java項(xiàng)目中,有兩個(gè)主要的構(gòu)建系統(tǒng):Gradle和Maven。構(gòu)建系統(tǒng)主要管理潛在的復(fù)雜依賴關(guān)系并正確編譯項(xiàng)目。還可以將已編譯的項(xiàng)目以及所有資源和源文件打包到.war或.jar文件中。對(duì)于簡(jiǎn)單的構(gòu)建,Maven和Gradle之間的選擇幾乎是個(gè)人喜好之一,或者也許是公司CTO或技術(shù)經(jīng)理的偏好。他們倆都是非常好的構(gòu)建工具。但是,對(duì)于更復(fù)雜的項(xiàng)目,Gradle比Maven更勝一籌。
一、Gradle構(gòu)建的利與弊
個(gè)人喜歡Gradle;我討厭XML,復(fù)雜的Java/Groovy
項(xiàng)目,如果沒(méi)有Gradle,幾乎是寸步難行的。除了沒(méi)有復(fù)雜的XML以外,Gradle還使用Groovy或Kotlin編寫(xiě)的構(gòu)建腳本提供了靈活性和更快的構(gòu)建速度。借助Kotlin或Groovy的全部功能以及Gradle API庫(kù),您可以創(chuàng)建功能強(qiáng)大且復(fù)雜的構(gòu)建腳本。這肯定是提升效率的工具。
對(duì)于DSL(特定于域的語(yǔ)言)需要一些時(shí)間來(lái)適應(yīng),并且Gradle以難以學(xué)習(xí)而著稱。但是,我認(rèn)為這主要是因?yàn)槿藗円呀?jīng)習(xí)慣了Maven
。使用Gradle,您實(shí)質(zhì)上可以學(xué)習(xí)一種構(gòu)建語(yǔ)言,而不只是簡(jiǎn)單地學(xué)習(xí)XML。與僅在Maven中添加依賴項(xiàng)相比,充分利用Gradle無(wú)疑具有更陡峭的學(xué)習(xí)曲線。但是向Gradle文件添加依賴項(xiàng)實(shí)際上并不比在Maven中困難。擴(kuò)展和自定義Gradle構(gòu)建比編寫(xiě)Maven插件和自定義構(gòu)建步驟要簡(jiǎn)單得多。
Gradle還極大地縮短了構(gòu)建時(shí)間,尤其是在大型項(xiàng)目中,因?yàn)镚radle僅處理已更改的任務(wù)和文件就可以很好地完成工作。此外,它提供了構(gòu)建緩存和構(gòu)建守護(hù)進(jìn)程,使重復(fù)構(gòu)建的性能更高。而且,像Maven一樣,它使用并行線程進(jìn)行依賴關(guān)系解析和項(xiàng)目構(gòu)建。同樣,對(duì)于小型,簡(jiǎn)單的構(gòu)建,這種性能提升可能并不明顯。但是對(duì)于較大的項(xiàng)目,這種性能提升是巨大的。
因此,總結(jié)一下。Gradle是:
- 大型項(xiàng)目更快
- 無(wú)限制可定制==更陡峭的學(xué)習(xí)曲線
- 使用Groovy或Kotlin代替XML
而Maven是:
- 普遍采用
- 對(duì)于較小項(xiàng)目更簡(jiǎn)單
- 帶有XML和尖括號(hào)
二、Groovy的優(yōu)點(diǎn)
簡(jiǎn)要介紹一下Groovy。Groovy是一種JVM語(yǔ)言,它可以編譯為與Java相同的字節(jié)碼,并且可以與Java類無(wú)縫地互操作。Groovy是Java的向后兼容超集,這意味著Groovy可以透明地與Java庫(kù)和代碼交互。但是,它還增加了許多新功能:可選的鍵入,函數(shù)式編程,運(yùn)行時(shí)靈活性以及許多元編程內(nèi)容。它還極大地清理了Java中許多冗長(zhǎng)的代碼格式。Groovy尚未成為主流的開(kāi)發(fā)語(yǔ)言,但是它已經(jīng)在測(cè)試(由于其簡(jiǎn)化的語(yǔ)法和元編程功能)和構(gòu)建系統(tǒng)中占據(jù)了一席之地。
三、依存關(guān)系
我們需要為本教程安裝一些內(nèi)容:
Java:您可能已經(jīng)安裝了Java。本教程至少需要Java 1.8。如果不是,請(qǐng)轉(zhuǎn)到官網(wǎng)下載并安裝它。
Gradle:但是,由于本教程是有關(guān)Gradle
的教程,因此在本教程中,您可以繼續(xù)進(jìn)行安裝。
四、認(rèn)識(shí)build.gradle
build.gradle
文件是Gradle項(xiàng)目的核心,是構(gòu)建配置必不可少的一項(xiàng)。就比如pom.xml對(duì)于Maven來(lái)說(shuō),這是等效的(沒(méi)有所有令人討厭的尖括號(hào))
讓我們來(lái)看一段:
// 配置運(yùn)行構(gòu)建腳本的要求 buildscript {? ? ? // 設(shè)置自定義屬性 ? ? ext { ? ? ? ? ?springBootVersion = '2.1.6.RELEASE'? ? ? } ? ? ? // 解決buildscript塊中的依賴項(xiàng)時(shí),檢查Maven Central中的依賴項(xiàng) ? ? repositories { ? ? ? ? ?mavenCentral() ? ? ? } ? ? ? // 我們需要spring boot插件來(lái)運(yùn)行構(gòu)建腳本 ? ? dependencies { ? ? ? ? ?classpath("org.springframework.boot:spring-boot-gradle-plugin:${springBootVersion}") ? ? ? } ? } ? ? ? // 添加構(gòu)建插件 apply plugin: 'java'? apply plugin: 'org.springframework.boot'? apply plugin: 'io.spring.dependency-management'? ? ? // 設(shè)置全局變量 group = 'com.okta.springboottokenauth'? version = '0.0.1-SNAPSHOT'? sourceCompatibility = 1.8? ? ? // 用于搜索以解決項(xiàng)目依賴關(guān)系的倉(cāng)庫(kù)地址 repositories { ? ? ? mavenCentral() ? } ? ? // 項(xiàng)目依賴 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
構(gòu)建文件的關(guān)鍵是要意識(shí)到它是一個(gè)腳本,內(nèi)置在Groovy DSL中。粗略地講,它是一個(gè)配置腳本,它調(diào)用定義了配置選項(xiàng)的一系列閉包(考慮函數(shù))。它看起來(lái)像JSON或propertiy
文件,盡管從技術(shù)上來(lái)說(shuō)這是錯(cuò)誤的。
但是,真正的有趣的來(lái)自build.gradle Groovy
腳本。因?yàn)樗梢詧?zhí)行任意代碼并訪問(wèn)任何Java庫(kù),特定于構(gòu)建的Gradle DSL和Gradle API。
五、Gradlebuildscript
讓我們從上至下查看腳本:
buildscript
閉包配置構(gòu)建腳本本身(與應(yīng)用程序相對(duì))所需的屬性,依賴項(xiàng)和源倉(cāng)庫(kù)。- 接下來(lái),
apply plugin
以非常好友的方式應(yīng)用了插件。這些擴(kuò)展了Gradle-Groovy DSL框架的基本功能:將該java插件與Spring Boot和Spring依賴項(xiàng)管理一起應(yīng)用。Java插件提供配置Gradle的期望標(biāo)準(zhǔn)的Java項(xiàng)目的目錄結(jié)構(gòu):src/main/java
,src/main/resources,src/test/java等,這些可以被配置為改變默認(rèn)的目錄或添加新的目錄。 - 接下來(lái),將一些標(biāo)準(zhǔn)屬性應(yīng)用于構(gòu)建。
repositories
塊定義了構(gòu)建腳本將在哪里尋找依賴關(guān)系。Maven Central
是最常見(jiàn)的(mavenCentral()),但也可以配置其他倉(cāng)庫(kù),包括自定義倉(cāng)庫(kù)和本地倉(cāng)庫(kù)??梢允褂脕?lái)將本地Maven
緩存配置為倉(cāng)庫(kù)mavenLocal()
。如果團(tuán)隊(duì)希望協(xié)調(diào)項(xiàng)目之間的構(gòu)建,但又不想將項(xiàng)目構(gòu)建文件實(shí)際捆綁在一起,這將很有幫助。- 最后,定義項(xiàng)目依賴項(xiàng)。
其中每個(gè)模塊定義閉包的順序無(wú)關(guān)緊要,因?yàn)榇蠖鄶?shù)build.gradle文件僅定義依賴項(xiàng),設(shè)置項(xiàng)目屬性并使用預(yù)定義的任務(wù),因此文件中元素的順序無(wú)關(guān)緊要。例如,沒(méi)有理由repositories
塊必須走在該dependencies
塊之前。您可以將build.gradle
文件視為Gradle在執(zhí)行調(diào)用它的shell命令分配的任何任務(wù)之前讀取的配置文件。
但是,當(dāng)您開(kāi)始使用Gradle
的功能來(lái)定義自定義任務(wù)并執(zhí)行任意代碼時(shí),它將變得更加復(fù)雜。Gradle將以build.gradle自上而下的方式讀取文件,并執(zhí)行在其中找到的所有代碼塊;根據(jù)此代碼的作用,它可以在腳本中創(chuàng)建強(qiáng)制排序。此外,當(dāng)您定義自定義任務(wù)和屬性(在Gradle API中找不到)時(shí),排序很重要,因?yàn)檫@些符號(hào)不會(huì)被預(yù)先定義,因此必須在構(gòu)建腳本中定義它們才能使用它們。
六、什么是閉包
回到Groovy剛問(wèn)世時(shí),函數(shù)式編程是相當(dāng)小眾的領(lǐng)域,將諸如閉包之類的東西帶入JVM感覺(jué)很瘋狂。如今,它變得更加普遍:Javascript
中的每個(gè)函數(shù)都是閉包。一般來(lái)說(shuō),閉包是具有范圍的一流函數(shù)。
這意味著兩件事:
- 閉包是可以在運(yùn)行時(shí)作為變量傳遞的函數(shù)
- 閉包保留對(duì)定義它們的變量范圍的訪問(wèn)
Java
版本的閉包稱為lambda
。這些是在1.8版中引入Java的,順便說(shuō)一句,這并不是在Groovy獲得最初的流行和函數(shù)式編程開(kāi)始發(fā)展的同時(shí)發(fā)生的。
為了演示lambda
,請(qǐng)看一下名為的JUnit測(cè)試LambdaTest.java。
src/test/java/com/okta/springboottokenauth/LambdaTest.java
interface SimpleLambda { ? ? ? public int sum(int x, int y); ? } ? ? ? public class LambdaTest { ? ? ? ? ? // 創(chuàng)建一個(gè)lambda函數(shù)? ? ? public SimpleLambda getTheLambda(int offset) { ? ? ? ? ? int scopedVar = offset; ? ? ? ? ? return (int x, int y) -> x + y + scopedVar; ? ? ? } ? ? ? ? ? @Test? ? ? public void testClosure() { ? ? ? ? ? // 測(cè)試lambda方法,當(dāng)offset=1 ? ? ? ? SimpleLambda lambda1 = getTheLambda(1); ? ? ? ? ? assertEquals(lambda1.sum(2,2), 5); ? ? ? ? ? ? ? // ?測(cè)試lambda方法,當(dāng)offset=2 ? ? ? ? SimpleLambda lambda2 = getTheLambda(2); ? ? ? ? ? assertEquals(lambda2.sum(2,2), 6); ? ? ? } }
這個(gè)示例很有代表性,演示了lambda
的兩個(gè)基本屬性。在閉包或lambda函數(shù)中,實(shí)現(xiàn)是在getTheLambda(int offset)
方法中定義的。創(chuàng)建lambda
時(shí),將offset變量封裝在閉包范圍中并返回。該lambda被分配給變量??梢灾貜?fù)調(diào)用它,并且它將引用相同的作用域。此外,可以使用封裝在單獨(dú)作用域中并分配給其他變量的新變量來(lái)創(chuàng)建新的lambda。
來(lái)自強(qiáng)大的面向?qū)ο蟮谋尘埃忾]最初感覺(jué)就像蟲(chóng)洞在嚴(yán)格的對(duì)象范圍連續(xù)體上打穿透孔一樣,奇怪地將對(duì)象的各個(gè)部分在空間和時(shí)間上連接在一起。
七、Gradle只是閉包
采取build.gradle文件的依賴項(xiàng)部分:
dependencies { ? ? ? implementation( 'com.okta.spring:okta-spring-boot-starter:1.2.1' ) ? ? ? implementation('org.springframework.boot:spring-boot-starter-security') ? ? ? ... }
沒(méi)有Groovy DSL速記,實(shí)際上是:
project.dependencies({ ? ? implementation( 'com.okta.spring:okta-spring-boot-starter:1.2.1' ) ? ? ? implementation('org.springframework.boot:spring-boot-starter-security') ? ? ? ...? })
括號(hào)中的所有內(nèi)容實(shí)際上都是傳遞給該project.dependencies()
方法的閉包。該project對(duì)象是Project該類的實(shí)例,該類是構(gòu)建的主要API父類。
這些函數(shù)將一系列依賴項(xiàng)作為字符串傳遞。那么,為什么不使用更傳統(tǒng)的靜態(tài)數(shù)據(jù)結(jié)構(gòu)(如JSON,屬性或XML)呢?原因是這些重載函數(shù)也可以使用閉包代碼塊,因此可以進(jìn)行深度自定義。
八、探索Gradle依賴項(xiàng)配置
依賴關(guān)系塊內(nèi)部是一系列配置和名稱:
dependencies { ? ? configurationName dependencyNotation }
我們的build.gradle
文件使用兩種配置:implementation
和testImplementation
。
implementation()
定義編譯時(shí)所需的依賴項(xiàng)。此配置方法稱為compile
。testImplementation()
并定義了僅用于測(cè)試(舊testCompile)所需的依賴項(xiàng)。
您可能會(huì)看到的另一個(gè)依賴項(xiàng)配置是runtimeOnly
和testRuntimeOnly
。這聲明了運(yùn)行時(shí)提供的不需要對(duì)其進(jìn)行編譯的依賴項(xiàng)。
定義依賴關(guān)系的方法比對(duì)本文的范圍有用的方法更多。幾乎可以說(shuō)任何東西都可以是依賴項(xiàng):本地文件,jar的目錄,另一個(gè)Gradle項(xiàng)目等等,并且可以將依賴項(xiàng)配置為執(zhí)行某些操作,例如排除某些子依賴項(xiàng)。
值得注意的是:Gradle和Maven以完全相同的方式解決依賴關(guān)系。例如,假設(shè)我們想從Spring Boot Starter中排除Log4j依賴關(guān)系,我們可以這樣做:
dependencies { ? ? ? implementation( 'com.okta.spring:okta-spring-boot-starter:1.2.1' ) { ? ? ? ? exclude group: 'org.apache.logging.log4j', module: 'log4j-api' ? ? } }
或者說(shuō)我們想將目錄中的所有文件都包含libs為依賴項(xiàng):
dependencies { ? ? ? implementation fileTree('libs') }
九、打包Gradle版本
關(guān)于Gradle的一件很棒的事情是Gradle包裝器。Gradle命令行為gradle。但是,您會(huì)注意到在網(wǎng)上的許多地方,您都會(huì)看到./gradlew或gradlew.bat。這些是調(diào)用包裝程序的命令。
包裝器允許項(xiàng)目捆綁在項(xiàng)目本身內(nèi)部構(gòu)建項(xiàng)目所需的Gradle版本。這樣可以確保對(duì)Gradle的更改不會(huì)中斷構(gòu)建。它還可以確保即使沒(méi)有安裝Gradle的人也可以運(yùn)行構(gòu)建。
它將以下文件添加到您的項(xiàng)目:
├── gradle │ ? └── wrapper │ ? ? ? ├── gradle-wrapper.jar │ ? ? ? └── gradle-wrapper.properties ├── gradlew └── gradlew.bat
gradlew和gradlew.bat是用于Linux/OSX和Window(分別)執(zhí)行腳本。他們運(yùn)行build.gradle使用捆綁的搖籃文件.jar的gradle/wrapper子目錄。
十、任務(wù)
任務(wù)是Gradle的核心。Java插件增加了十幾個(gè)任務(wù),包括:clean
,compile
,test
,jar
,和uploadArchives
。Spring Boot
插件添加了bootRun任務(wù),該任務(wù)運(yùn)行Spring Boot應(yīng)用程序。
通常,任務(wù)是這樣運(yùn)行的:gradle taskName otherTaskName
,或使用包裝器:./gradlew taskName otherTaskName
。
如果打開(kāi)終端并cd進(jìn)入示例項(xiàng)目的基本目錄,則可以使用gradle tasks列出build.gradle文件定義的所有任務(wù)。tasks當(dāng)然,它本身是由基本Gradle API定義的任務(wù)。
> 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
任務(wù)。它將列出一棵樹(shù),其中包含項(xiàng)目所需的所有依賴關(guān)系(包括子依賴關(guān)系)。嘗試gradle dependencies
在項(xiàng)目根目錄中運(yùn)行。您可以使用該dependencyInsight任務(wù)來(lái)深入了解特定的子依賴項(xiàng)。
另一個(gè)有助于解決問(wèn)題的properties
任務(wù)是該任務(wù),該任務(wù)列出了在根項(xiàng)目對(duì)象實(shí)例上定義的所有屬性。
當(dāng)然,在開(kāi)發(fā)Spring Boot項(xiàng)目時(shí),可以使用命令:./gradlew bootJar,該任務(wù)將項(xiàng)目及其依賴項(xiàng)打包在一個(gè)jar文件中。
到此,基礎(chǔ)篇完事兒,提高篇中將會(huì)實(shí)踐一下自定義任務(wù)和Groovy閉包在Gradle配置文件build.gradle文件中如何使用。
到此這篇關(guān)于Java中的Gradle與Groovy的區(qū)別及存在的關(guān)系的文章就介紹到這了,更多相關(guān)Java中的Gradle與Groovy內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
RocketMQ NameServer保障數(shù)據(jù)一致性實(shí)現(xiàn)方法講解
這篇文章主要介紹了RocketMQ NameServer保障數(shù)據(jù)一致性實(shí)現(xiàn)方法,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-12-12Java驗(yàn)證時(shí)間格式是否正確方法類項(xiàng)目實(shí)戰(zhàn)
在很多場(chǎng)景中我們需要驗(yàn)證時(shí)間日期的是否屬于正確的格式,驗(yàn)證時(shí)間是否符合常規(guī)的,本文就來(lái)介紹一下幾種方式,感興趣的可以了解一下2022-04-04spring學(xué)習(xí)之@SessionAttributes實(shí)例解析
這篇文章主要介紹了spring學(xué)習(xí)之@SessionAttributes實(shí)例解析,分享了相關(guān)代碼示例,小編覺(jué)得還是挺不錯(cuò)的,具有一定借鑒價(jià)值,需要的朋友可以參考下2018-02-02Intellij IDEA命令行執(zhí)行java無(wú)法加載主類解決方案
這篇文章主要介紹了Intellij IDEA命令行執(zhí)行java無(wú)法加載主類解決方案,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-09-09SpringBoot結(jié)合mockito測(cè)試實(shí)戰(zhàn)
與集成測(cè)試將系統(tǒng)作為一個(gè)整體測(cè)試不同,單元測(cè)試更應(yīng)該專注于某個(gè)類。所以當(dāng)被測(cè)試類與外部類有依賴的時(shí)候,尤其是與數(shù)據(jù)庫(kù)相關(guān)的這種費(fèi)時(shí)且有狀態(tài)的類,很難做單元測(cè)試。但好在可以通過(guò)“Mockito”這種仿真框架來(lái)模擬這些比較費(fèi)時(shí)的類,從而專注于測(cè)試某個(gè)類內(nèi)部的邏輯2022-11-11