相信使用 Java 的同学都用过 Maven,这是一个非常经典好用的项目构建工具。但是如果你经常使用 Maven,可能会发现 Maven 有一些地方用的让人不太舒服:
- 一来 Maven 的配置文件是 XML 格式的,假如你的项目依赖的包比较多,那么 XML 文件就会变得非常非常长;
- 二来 XML 文件不太灵活,假如你需要在构建过程中添加一些自定义逻辑,搞起来非常麻烦;
- 第三就是 Maven 非常的稳定,但是相对的就是对新版 java 支持不足,哪怕就是为了编译 java11,也需要更新内置的 Maven 插件。
如果你对 Maven 的这些缺点也有所感触,准备尝试其他的构建工具,那么你可以试试 gradle,这是一个全新的 java 构建工具,解决了 Maven 的一些痛点。
安装 gradle
最传统的安装方法就是去 gradle 官网下载二进制包,解压,然后将路径添加到环境变量中。如果你没什么其他需求,可以使用这种安装方式。但是,gradle 是一个非常新潮的项目,每隔几个月就会发布一个新版本,这种方式可能跟不上 gradle 的更新速度。
所以我更加推荐使用包管理器来安装 gradle。如果你使用 linux 系统,那么不必多说。如果你使用 Windows 系统,我推荐使用 scoop 包管理器来安装 gradle。它安装方便,而且使用 SHIM 目录来管理环境变量,在各种工具中配置 gradle 也很方便。
当然,如果你完全不喜欢安装这么多乱七八糟的东西,那也可以使用 gradle。gradle 提供了一个名为 gradle wrapper 的工具,可以在没有安装 gradle 的情况下使用 gradle。好吧,其实它就是个脚本文件,当你运行 wrapper 脚本的时候,如果脚本发现你电脑里没有 gradle,就会自动替你下载安装一个。现在甚至还出现了 Maven wrapper,也是个脚本文件,可以自动安装 Maven。
之前相信一些朋友听说过 gradle,然后尝试使用它,结果因为速度太慢,最后放弃了。之前我也因为 gradle 的速度,放弃了它一段时间。不过现在使用 gradle 的话会方便很多。gradle 官方在中国开设了,CDN,使用 gradle wrapper 的时候下载速度非常快。可以说现在是一个学习使用 gradle 的好时候。
使用 gradle wrapper
这里我使用的 IDEA 来创建和使用 gradle 项目。
IDEA 默认就会使用 gradle wrapper 来创建项目,所以无需安装 gradle 也可以正常运行。这时候项目结构应该类似下图所示,使用 Maven 的同学应该比较熟悉,因为这和 Maven 的项目结构几乎完全一致。gradle 文件夹和 gradlew 那几个文件就是 gradle wrapper 的文件,而.gradle 后缀名的文件正是 gradle 的配置文件,对应于 Maven 的 pom.xml。
gradle wrapper 的优点之一就是可以自定义下载的 gradle 的版本,如果是团队协作的话,这个功能就非常方便,简单设置即可统一团队的构建工具版本。这里我就设定成目前最新的 gradle 6.4.默认下载安装的是 bin 版,仅包含二进制。如果你使用 IDEA 的话,它会推荐下载 all 版,包含源代码,这样 IDEA 就可以分析源代码,提供更加精确的 gradle 脚本支持。
依赖管理
下面来看看 gradle 的依赖管理功能,这也算是我们使用构建工具的主要目的之一了。这点也是 gradle 相较 maven 的优势之一了。相较于 maven 一大串的 XML 配置,gradle 的依赖项仅需一行。
dependencies {
testImplementation 'junit:junit:4.13'
implementation 'com.google.code.gson:gson:2.8.6'
}
这里推荐一下 Jetbrains 的 package search 网站,是寻找 maven 和 gradle 依赖包的最佳网站,可以非常轻松的搜索和使用依赖项。
gradle 依赖的粒度控制相较于 Maven 也更加精细,maven 只有 compile、provided、test、runtime 四种 scope,而 gradle 有以下几种 scope:
- implementation,默认的 scope。implementation 的作用域会让依赖在编译和运行时均包含在内,但是不会暴露在类库使用者的编译时。举例,如果我们的类库包含了 gson,那么其他人使用我们的类库时,编译时不会出现 gson 的依赖。
- api,和 implementation 类似,都是编译和运行时都可见的依赖。但是 api 允许我们将自己类库的依赖暴露给我们类库的使用者。
- compileOnly 和 runtimeOnly,这两种顾名思义,一种只在编译时可见,一种只在运行时可见。而 runtimeOnly 和 Maven 的 provided 比较接近。
- testImplementation,这种依赖在测试编译时和运行时可见,类似于 Maven 的 test 作用域。
- testCompileOnly 和 testRuntimeOnly,这两种类似于 compileOnly 和 runtimeOnly,但是作用于测试编译时和运行时。
通过简短精悍的依赖配置和多种多样的作用与选择,Gradle 可以为我们提供比 Maven 更加优秀的依赖管理功能。
gradle 的任务和插件
gradle 的配置文件是一个 groovy 脚本文件,在其中我们可以以编程方式自定义一些构建任务。因为使用了编程方式,所以这带给了我们极大的灵活性和便捷性。打个比方,现在有个需求,要在打包出 jar 的时候顺便看看 jar 文件的大小。在 gradle 中仅需在构建脚本中编写几行代码即可。而在 Maven 中则需要编写 Maven 插件,复杂程度完全不在一个水平。
当然,Maven 发展到现在,已经存在了大量的插件,提供了各式各样的功能可以使用。但是在灵活性方面还是无法和 Gradle 相比。而且 Gradle 也有插件功能,现在发展也十分迅猛,存在了大量非常好用的插件,例如 gretty 插件。gretty 原来是社区插件,后来被官方吸收为官方插件,可以在 Tomcat 和 jetty 服务器上运行 web 项目,比 Maven 的相关插件功能都强大。
虽然 gradle 可以非常灵活的编写自定义脚本任务,但是其实一般情况下我们不需要编写构建脚本,利用现有的插件和任务即可完成相关功能。在 IDEA 里,也可以轻松的查看当前 gradle 项目中有多少任务,基本任务如 build、test 等 Maven 和 Gradle 都是相通的。
配置镜像
Maven 官方仓库的下载速度非常慢,所以一般我们要配置国内的镜像源。gradle 在这方面和 Maven 完全兼容,因此只需稍微配置一下镜像源,即可使用 Maven 的镜像。如果你用 gradle 构建过项目,应该就可以在用户目录的.gradle 文件夹下看到 gradle 的相关配置和缓存。
之前 wrapper 下载的 gradle 也存放在该文件夹下,位置是 wrapper/dists。
而依赖的本地缓存在 caches\modules-2\files-2.1 文件夹下。目录结构和 Maven 的本地缓存类似,都是包名 + 版本号的方式,但是 gradle 的目录结构最后一层和 Maven 不同,这导致它们无法共用本地缓存。
言归正传,在 gradle 中配置下载镜像需要在.gradle 文件夹中直接新建一个 init.gradle 初始化脚本,脚本文件内容如下。这样一来,gradle 下载镜像的时候就会使用这里配置的镜像源下载,速度会快很多。再加上 gradle wrapper 在中国设置了 CDN,现在使用 gradle 的速度应该会很快。
allprojects {
repositories {
maven {
url "https://maven.aliyun.com/repository/public"
} maven { url "https://maven.aliyun.com/repository/jcenter"
} maven { url "https://maven.aliyun.com/repository/spring"
} maven { url "https://maven.aliyun.com/repository/spring-plugin"
} maven { url "https://maven.aliyun.com/repository/gradle-plugin"
} maven { url "https://maven.aliyun.com/repository/google"
} maven { url "https://maven.aliyun.com/repository/grails-core"
} maven { url "https://maven.aliyun.com/repository/apache-snapshots"
} }}
当然,如果你有代理的话,其实我推荐你直接为 gradle 设置全局代理。因为 gradle 脚本实在是太灵活了,有些脚本中可能依赖了 github 或者其他地方的远程脚本。这时候上面设置的下载镜像源就不管用了。
所以有条件还是干脆直接使用全局代理比较好。设置方式很简单,在.gradle 文件夹中新建 gradle.properties 文件,内容如下。中间几行即是设置代理的配置项。当然其他几行我也建议你设置一下,把 gradle 运行时的文件编码设置为 UTF8,增加跨平台兼容性。
org.gradle.jvmargs=-Xmx4g -XX:MaxPermSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8
systemProp.http.proxyHost=127.0.0.1
systemProp.http.proxyPort=10800
systemProp.https.proxyHost=127.0.0.1
systemProp.https.proxyPort=10800
systemProp.file.encoding=UTF-8
org.gradle.warning.mode=all
为什么使用 gradle?
看到这里,你应该对 gradle 有了基本的了解, 也可以将其用于你的项目之中。但是如果你 Maven 已经非常熟悉了,可能不太愿意使用 gradle,因为貌似没有必要。但是既然 gradle 出现了,就说明有很多人对 Maven 还是有一定的意见。因此在这里我来总结一下 gradle 相比 maven 的优势。
首先第一点也就是最重要的一点就是速度。gradle 使用构建缓存、守护进程等方式提高编译速度。结果就是 gradle 的编译速度要远超 maven,平均编译速度比 Maven 快好几倍,而且项目越大,这个差距就越明显。
第二点就是灵活性,gradle 要比 Maven 灵活太多,虽然有时候灵活并不是一件好事情。但是大部分情况下,灵活一点可以极大的方便我们。Maven 死板的 XML 文件方式做起事情来非常麻烦。很多 Maven 项目都通过执行外部脚本的方式来完成一些需要灵活性的工作。而在 gradle 中配置文件就是构建脚本,构建脚本就是编程语言(groovy 编程语言),完全可以自给自足,无需外部脚本。
第三点就是 gradle DSL 带来的简洁性。完成同样的功能,gradle 脚本的长度要远远短于 maven 配置文件的长度。虽然很多人都说 XML 维护起来不麻烦,但是我觉得,维护一个光是依赖就有几百行的 XML 文件,不见得就比 gradle 脚本简单。
也许是因为我上面说的原因,也许有其他原因,不得不承认的一件事情就是 gradle 作为一个新兴的工具已经有了广泛的应用。spring 等项目已经从 Maven 切换到了 gradle。开发安卓程序也只支持 gradle 了。因此不管是否现在需要将项目从 maven 切换到 gradle,但是至少学习 gradle 是一件必要的事情。
欢迎来到这里!
我们正在构建一个小众社区,大家在这里相互信任,以平等 • 自由 • 奔放的价值观进行分享交流。最终,希望大家能够找到与自己志同道合的伙伴,共同成长。
注册 关于