Gradle与Maven的抉择

对于项目管理工具,大家对于Maven并不陌生。很多著名的项目都是采用Maven来构建和管理的,可以说,Maven已然是Java界项目管理事实上的标准了。那么,在这里,我们为什么还要介绍Gradle,Gradle 相比较Maven而言,有哪些优势?

对于上述问题,本节我们将一一揭晓。

Maven概述

长期以来,在Java编程界, Ant 和Ivy分别实现了Java 程序的编译及依赖管理。Maven 的出现将这两个功能合二为一。

滚动鼠标轴或单击,开始截长图对于Maven用户来说,依赖管理是理所当然的。Maven 不仅内置了依赖管理,更有一个可能拥有全世界最多Java 开源软件包的中央仓库,Maven用户无须进行任何配置,就可以直接享用。

除此之外,企业也可以在自已的网络中搭建Maven镜像库,从而加快下载依赖的速度。

1. Maven生命周期

Maven主要有以下三种内建的生命周期。

default:用于处理项目的构建和部署。

clean:用于清理Maven产生的文件和文件夹。

site:用于处理项目文档的创建。

在实际使用中,我们无须明确指定生命周期。相反,我们只需要指定一一个阶段。 Maven会根据

指定的阶段来推测生命周期。

例如,当Maven以package为运行参数时,default 生命周期就会得到执行。Maven会按顺序运行所有阶段。

每个生命周期,都有自己的一系列的阶段。

clean: clean 阶段,清理Maven产生的文件和文件夹。

site: site 阶段,会生成项目的文档。

default:以下是default生命周期所包含的主要的阶段:

* validate: 该阶段用于验证所有项目的信息是否可用和正确;

* process-resources: 该阶段复制项目资源到发布包的位置;

* compile: 该阶段用于编译源码;

*test:该阶段结合框架执行特定的单元测试;.

*package:该阶段按照特定的发布包的格式来打包编译后的源码;

* integration-test: 该阶段用于处理集成测试环境中的发布包;

* verify: 该阶段运行校验发布包是否可用;

* install: 该阶段安装发布包到本地库; .

*deploy:该阶段安装最终的发布包到配置的库。

每个阶段都由插件目标( goal )组成。插件目标是构建项目的特定任务。

一些目标只在特定阶段才有意义,例如,Maven的compile目标,Maven Compiler插件在compile阶段是有意义的,但是Maven Checkstyle插件的checkstyle 目标可能会在任何阶段运行。所以有一些目标必然属于具体的某个生命周期的阶段,而另一些则不是。

以下是-一个阶段、插件和目标对应表,如表2-3所示。




gradle与maven依赖冲突 gradle与maven哪个好_maven多模块合并打包


2.依赖管理

依赖管理是Maven的核心功能。Maven 为Java世界引入了一个新的依赖管理系统。在Java世界中,可以用groupld、artifactld、 version 组成的Coordination (坐标)唯一标识- 一个依赖。任何基.于Maven构建的项目自身也必须定义这三项属性,生成的包可以是jar包,也可以是war包或ear包。

以下是一个典型的Maven依赖库的坐标。

org. springf ramework . bootspring-boot-starter-web2.0.0.M4 version> dependency>

在依赖管理中,另-个非常重要的概念是scope (范围)。Maven 有6种不同的scope。

● compile: 默认就是compile, 什么都不配置也就是意味着compile。 compile表示被依赖项目需要参与当前项目的编译,当然后续的测试,运行周期也参与其中,是-一个比较强的依赖。打包的时候通常需要包含进去。

●test: 此类依赖项目仅仅参与测试相关的工作,包括测试代码的编译和执行。一般在运行时不需要这种类型的依赖。

● runtime: 表示被依赖项目无须参与项目的编译,不过后期的测试和运行周期需要其参与。一个典型的例子是logback, 你希望使用Simple Logging Facade for Java (slf4j )来记录日志,并使用logback绑定。

● provided: 该类依赖只参与编译和运行时,但并不需要在发布时打包进发布包。一个典型的例子是servlet-api,这类依赖通常会由应用服务来提供。

● system: 从参与度来说,与provided相同,不过被依赖项不会从Maven仓库获取,而是从本地文件系统获取,所以一定需要配合systemPath属性使用。以下是-一个例子。

com. waylau. springboot2.0system scope>$ {basedir}/ 1ib/boot. jar systemPath>

●import:这仅用于依赖关系管理部分中pom类型的依赖。它表示指定的pom应该被替换为该

pom的dependencyManagement部分中的依赖关系。这是为了集中大型多模块项目的依赖关系。

3.多模块构建

Maven支持多模块构建。在现代的项目中,经常需要将一个大型软件产 品划分为多个模块来进行开发,从而实现软件项目的“高内聚、低耦合”。

Maven的多模块构建是通过一个名为项目继承( Project Inheritance )的功能来实现的。Maven允许将一些需要继承的元素,在父pom文件中进行指定。

一般来说,多模块项目包含-一个父模块, 以及多个子模块。下面是-个父模块的pom文件的例子。

com. waylau. springproject-with- inheritancepom1.0.0

那么,在子模块的pom中需要指定父模块。

com. waylau. spring groupId>project-wi th- inheritance1.0.04.0.0childjarChild Project

Gradle概述

Gradle是一个基于Ant和Maven概念的项目自动化构建工具。与Ant和Maven最大的不同之处在于,它使用一种基于Groovy的特定领域语言(DSL)来声明项目设置,抛弃了传统的基于XML的各种烦琐配置。

1. Gradle生命周期

Gradle是基于编程语言的,我们可以自己定义任务( task )和任务之间的依赖,Gradle 会确保有顺序地去执行这些任务及依赖任务,并且每个任务只执行- -次。当任务执行的时候,Gradle 要完成任务和任务之间的定向非循环图( Directed Acyclic Graph)。

Gradle构建主要有三个不同的阶段。

初始化阶段( Initialization) : Gradle 支持单个和多个项目的构建。Gradle 在初始化阶段决定哪些项目( project)参与构建,并且为每个项目创建一个 Project类的实例对象。

配置阶段( Configuration) :在这个阶段配置每个Project 的实例对象。然后执行这些项目脚本中的一部分任务。

执行阶段( Execution) : Gradle 确定任务的子集,在配置界面创建和配置这些任务,然后执行任务。这些子集任务的名称当成参数传递给gradle命令和当前目录。接着, Gradle 执行每-一个选择的任务。

2.依赖管理

通常,一个项目的依赖会包含自己的依赖。例如,Spring 的核心需要几个其他包在类路径中存在才能运行。所以,当Gradle运行项目的测试,它也需要找到这些依赖关系,使它们存在于项目中。

Gradle借鉴了Maven里面依赖管理很多的优点,甚至可以重用Maven中央库。你也可以将自己的项目上传到- -个远程Maven库中。这也是Gradle能够成功的非常重要的原因一-站在巨人的肩膀之上,而非重复发明轮子。

下面是Gradle声明依赖的例子。

apply plugin: 'java'repositories {mavenCentral ()dependencies {compile group: ' org .hibernate',name:' hibernate-core',version:13.6.7.Final↑testCompile group: ' junit', name: 'junit', version: '4.+'

这个脚本说明了几个问题。首先,声明使用了Java插件。其次,项目需要Hibernate core3.6.7.Final版本来编译。其中隐含的意思是,Hibernate core和它的依赖在运行时是需要的。最后,需要junit >= 4.0版本在测试时编译。同时,告诉Gradle依赖要在Maven中央库中寻找。

Java插件为Gradle项目添加了一些依赖关系配置,如表2-4所示。它将这些配置分配给诸如compileJava和test之类的任务。


gradle与maven依赖冲突 gradle与maven哪个好_maven多模块合并打包_02


图2-10展示了Gradle依赖配置图。


gradle与maven依赖冲突 gradle与maven哪个好_maven多模块合并打包_03


3.多项目构建

Gradle天然地支持多项目构建。

以下是一个多项目构建的例子。在该例子中有一个父项目,以及两个Web应用程序的子项目。

整个构建布局如下。

webDist/settings. gradlebuild. gradledate/src/main/java/org/gradle/ sample/DateServlet. javahello/src/main/java/org/gradle/ sample/HelloServlet. java

其中,settings.gradle 文件包含如下内容。

include 'date', 'hello'

build.gradle文件包含如下内容。

allprojectsapply plugin: 'java 'group = ' org . gradle. sample 'version = '1.0'subprojects {apply plugin: 'war'repositories {mavenCentral ()dependencies {compile "javax.servlet:servlet-api:2.5"task explodedDist (type: Copy) {into "$buildDir/explodedDis t"subprojects {from tasks . withType (War)

Gradle与Maven的对比

Gradle 号称是下一-代的构建工具,吸取了Maven等构建工具的优势,所以在- 开始的设计上,就比较前瞻。从上面的Gradle和Maven概述中,我们也能大概了解到这两个构建工具的异同点。

  1. 一致的项目结构

对于源码而言,Gradle 与Maven拥有一致的项目结构,以下是项目结构的例子。


gradle与maven依赖冲突 gradle与maven哪个好_Gradle_04


Gradle与Maven同样都遵循“约定大于配置”的原则,以最大化减少项目的配置。

2.一致的仓库.

Gradle借鉴了Maven的坐标表示法,都可以用groupld、artifactld、 version 组成的坐标来唯一标识一个依赖。

在类库的托管方面,Gradle 并没有自己去创建独立的类库托管平台,而是可以直接使用Maven托管类库的仓库。

下面是一个在Gradle中指定托管仓库的例子。

//使用了Maven的中央仓库及Spring自己的仓库(也可以指定其他仓库)repositoriesmavenCentral ()maven { url "https:/ / repo. spring. io/ snapshot" }maven { url "https:/ /repo. spring. io/milestone" }

3.支持大型软件的构建

对于大型软件构建的支持,Maven 采用了多模块的概念,而Gradle采用了多项目的概念,两者本质上都是为了简化大型软件的开发。

4.丰富的插件机制

Gradle和Maven都支持插件机制,而且社区对于这两款构建工具的插件的支持都非常丰富。

5. Groovy而非XML

在依赖管理的配置方面,Gradle 采用了Groovy语言来描述,而非传统的XML。XML的好处是语言严谨,这也是为什么在Web服务中采用XML来作为信息交换的格式。但这同样也带来了一一个弊端,那就是灵活度不够。而Groovy本身是-一门编程语言,所以在灵活性方面更胜一筹。

另方面,Groovy在表达依赖关系时,比XML拥有更加简洁的表示方式。例如,下面在Maven中引用Spring Boot依赖的例子。

org . spr ingf ramework . bootspring-boot-starters arti factId>2.0.0.M4 dependency>

如果换作是Gradle,仅仅只需一-行配置。可以改用以下的方式。

compile(' org. spr ingf ramework . boot :spring-boot-starter-web:2.0.0.M4')从这个小小的例子就能看出,XML对于Gradle的配置脚本而言,是多么低效和冗余!

6.性能比对

相比较Maven而言,Gradle 的性能可以说是一大亮点。图2-11是Gradle团队所做的性能测试报告,测试中选取了Gradle 3.4与Gradle 3.3及Maven 3.3.9三个版本进行性能对比。


gradle与maven依赖冲突 gradle与maven哪个好_maven多模块合并打包_05


从图2-11中可以明显地看到,Gradle 3.4版本较之Maven有着10 倍以上的性能!这也是广大开发者采用Gradle的非常重要的原因。

总结

我们已经对Gradle与Maven做了优势比较。Maven 在Java领域仍然拥有非常高的占有率,但在将来,越来越多的团队已经开始转向了Gradle,如Linkin、Android Studio、Netflix、 Adobe 、Elasticsearch等,毕竟无论是在配置的简洁性方面,还是在性能方面,Gradle 都更胜一筹。这也是为什么本文选用Gradle来作为构建工具。

注意:本文所有的示例,都是采用Gradle来进行项目的管理。如有需要,读者也可以将项目源码自行转化为Maven等管理方式。