Maven和Gradle,纯干货

聊聊生命周期

废话不说,先放一张Maven的生命周期图。

《Maven和Gradle,纯干货》 image.png

说的简单点,Maven的生命周期是有顺序依赖关系的,如果你指定了某个阶段,比如到package阶段,那么package之前的所有阶段都会被顺序执行到。

《Maven和Gradle,纯干货》 image.png

反观Gradle构建这边,包括编译主代码、处理资源、编译测试代码、执行测试、上传归档等等任务。

《Maven和Gradle,纯干货》 image.png

相对于Maven完全线性的生命周期,Gradle的构建生命周期略微复杂,不过也更为灵活,例如jar这个任务是用来打包的,它不像Maven那样依赖于执行测试的test任务,类似的,从图中可以看到,一个最终的build任务也没有依赖于uploadArchives任务。这个生命周期并没有将用户限制得很死,举个例子,我希望每次build都发布 SNAPSHOT版本到Maven仓库中,而且我只想使用最简单的$ gradle clean build命令,那只需要添加一行任务依赖配置即可:
build.dependsOn ‘uploadArchives’
由于Gradle完全是基于灵活的任务模型,因此很多事情包括覆盖现有任务,跳过任务都非常易于实现。而这些事情,在Maven的世界中,实现起来就比较的麻烦,或者说Maven压根就不希望用户这么做。

聊聊用法简洁性

我们知道依赖管理、仓库、约定优于配置等概念是Maven的核心内容,抛开其实现是否最优不谈,概念本身没什么问题,并且已经被广泛学习和接受。那Gradle实现了这些优秀概念了么?答案是肯定的。
先看依赖管理,我有一个简单的项目依赖于一些第三方类库包括SpringFramework、JUnit、Kaptcha等等。原来的Maven POM配置大概是这样的(篇幅关系,省略了部分父POM配置):
<properties>
<kaptcha.version>2.3</kaptcha.version>
</properties>

<dependencies>
    <dependency>
        <groupId>com.google.code.kaptcha</groupId>
        <artifactId>kaptcha</artifactId>
        <version>${kaptcha.version}</version>
        <classifier>jdk15</classifier>
    </dependency>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-core</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-beans</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-context</artifactId>
    </dependency>
    <dependency>
        <groupId>junit</groupId>
        <artifactId>junit</artifactId>
    </dependency>
</dependencies>

然后我将其转换成Gradle脚本,结果是惊人的:

dependencies {
compile(‘org.springframework:spring-core:2.5.6’)
compile(‘org.springframework:spring-beans:2.5.6’)
compile(‘org.springframework:spring-context:2.5.6’)
compile(‘com.google.code.kaptcha:kaptcha:2.3:jdk15’)
testCompile(‘junit:junit:4.7’)
}

注意配置从原来的28行缩减至7行!这还不算我省略的一些父POM配置。依赖的groupId、artifactId、 version,scope甚至是classfier,一点都不少。较之于Maven或者Ant的XML配置脚本,Gradle使用的Grovvy脚本杀伤力太大了,爱美之心,人皆有之,相比于七旬老妇松松垮垮的皱纹,大家肯定都喜欢少女紧致的脸蛋,XML就是那老妇的皱纹。
关于Gradle的依赖管理起初我有一点担心,就是它是否有传递性依赖的机制呢?经过文档阅读和实际试验后,这个疑虑打消了,Gradle能够解析现有的Maven POM或者Ivy的XML配置,从而得到传递性依赖的信息,并且引入到当前项目中,这实在是一个聪明的做法。在此基础上,它也支持排除传递性依赖或者干脆关闭传递性依赖,其中第二点是Maven所不具备的特性。
自动化依赖管理的基石是仓库,Maven中央仓库已经成为了Java开发者不可或缺的资源,Gradle既然有依赖管理,那必然也得用到仓库,这当然也包括了Maven中央仓库,就像这样:

repositories {
mavenLocal()
mavenCentral()
mavenRepo urls: “http://repository.sonatype.org/content/groups/forge/
}

这段代码几乎不用解释,就是在Gradle中配置使用Maven本地仓库、中央仓库、以及自定义地址仓库。在我实际构建项目的时候,能看到终端打印的下载信息,下载后的文件被存储在USER_HOME/.gradle/cache/ 目录下供项目使用,这种实现的方法与Maven又是及其类似了,可以说Gradle不仅最大限度的继承Maven的很多理念,仓库资源也是直接拿来用。
Gradle项目使用Maven项目生成的资源已经不是个问题了,接着需要反过来考虑,Maven用户是否能够使用 Gradle生成的资源呢?或者更简单点问,Gradle项目生成的构件是否可以发布到Maven仓库中供人使用呢?这一点非常重要,因为如果做不到这一点,你可能就会丢失大量的用户。幸运的是Gradle再次给出了令人满意的答案。使用Gradle的Maven Plugin,用户就可以轻松地将项目构件上传到Maven仓库中:

apply plugin: ‘maven’

uploadArchives {
repositories.mavenDeployer {
repository(url: “http://localhost:8088/nexus/content/repositories/snapshots/“) {
authentication(userName: “admin”, password: “admin123”)
pom.groupId = “com.juvenxu”
pom.artifactId = “account-captcha”
}
}
}

在上传的过程中,Gradle能够基于build.gradle生成对应的Maven POM文件,用户可以自行配置POM信息,比如这里的groupId和artifactId,而诸如依赖配置这样的内容,Gradle是会自动帮你进行转换的。由于Maven项目之间依赖交互的直接途径就是仓库,而Gradle既能够使用Maven仓库,也能以Maven的格式将自己的内容发布到仓库中,因此从技术角度来说,即使在一个基于Maven的大环境中,局部使用Gradle也几乎不会是一个问题。

总结下

Maven不允许扩展,基本按照约定进行构建,没有Gradle简洁灵活,但是Gradle的灵活,或许会带来新的问题,但是目前,我还没有机会灵活构建一把Gradle的项目。

福利

如果用Gradle,可以直接用IntelliJ IDEA,因为它很好的集成了Gradle,不需要额外下载Gradle的插件,在编译的时候,它会自动去下载Gradle的相关东西,然后你就可以看到你的Gradle项目根目录下,已经存在了gradle。

《Maven和Gradle,纯干货》 image.png

额外要说的是,开始看了那么多资料,想要装逼在IntelliJ的terminal(Alt + F12)窗口用gradle的命令,例如, gradle Build/gradle bootRun,云云,却没有成功,后来在Gradle的官网上看到了这个gradlew,我才尝试用 gradlew Build/gradlew bootRun, 运行成功。网上的资料好坑爹啊。

《Maven和Gradle,纯干货》 image.png

参考资料

Maven进阶:Maven的生命周期

Maven和Gradle的区别

Gradle 官方Guides

使用Gradle创建一个最简单的Spring Boot项目

如果你不需要依赖IntelliJ IDEA,你也可以自己下载Gradle来搭建环境。
Gradle 环境搭建
Gradle编译时下载依赖失败解决方法

    原文作者:科学Jia
    原文地址: https://www.jianshu.com/p/819bcb195b3c
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞