gradle和maven的对比

Java世界中主要有三大构建工具:Ant、Maven和Gradle。经过几年的发展,Ant几乎销声匿迹、Maven也日薄西山,而Gradle的发展则如日中天。笔者有幸见证了Maven的没落和Gradle的兴起。Maven的主要功能主要分为5点,分别是依赖管理系统、多模块构建、一致的项目结构、一致的构建模型和插件机制。我们可以从这五个方面来分析一下Gradle比起Maven的先进之处。

Maven为Java世界引入了一个新的依赖管理系统。在Java世界中,可以用groupId、artifactId、version组成的Coordination(坐标)唯一标识一个依赖。任何基于Maven构建的项目自身也必须定义这三项属性,生成的包可以是Jar包,也可以是war包或者ear包。一个典型的依赖引用如下所示:

<dependency>
 <groupId>junit</groupId>
 <artifactId>junit</artifactId>
 <version>4.12</version>
 <scope>test</scope>
</dependency>
    
<dependency>
 <groupId>org.springframework</groupId>
 <artifactId>spring-test</artifactId>
</dependency>

从上面可以看出当引用一个依赖时,version可以省略掉,这样在获取依赖时会选择最新的版本。而存储这些组件的仓库有远程仓库和本地仓库之分。远程仓库可以使用世界公用的central仓库,也可以使用Apache Nexus自建私有仓库;本地仓库则在本地计算机上。通过Maven安装目录下的settings.xml文件可以配置本地仓库的路径,以及采用的远程仓库的地址。

Gradle沿用了maven的依赖管理系统,区别以下:

  1. 引入的依赖很简洁

  2. 在Maven世界中,一个依赖项有6种scope,分别是complie(默认)、provided、runtime、test、system、import。而grade将其简化为了4种,compile、runtime、testCompile、testRuntime???

  3. Gradle支持动态的版本依赖。在版本号后面使用+号的方式可以实现动态的版本管理。

  4. 多模块构建

    在SOA和微服务的浪潮下,将一个项目分解为多个模块已经是很通用的一种方式。在Maven中需要定义个parent POM作为一组module的聚合POM。在该POM中可以使用标签来定义一组子模块。parent POM不会有什么实际构建产出。而parent POM中的build配置以及依赖配置都会自动继承给子module。

    而Gradle也支持多模块构建。而在parent的build.gradle中可以使用allprojects和subprojects代码块来分别定义里面的配置是应用于所有项目还是子项目。对于子模块的定义是放置在setttings.gradle文件中的。在gradle的设计当中,每个模块都是Project的对象实例。而在parent build.gradle中通过allprojects或subprojects可以对这些对象进行各种操作。这无疑比Maven要灵活的多。

    比如在parent的build.gradle中有以下代码:

    一致的项目结构
    在Ant时代大家创建Java项目目录时比较随意,然后通过Ant配置指定哪些属于source,那些属于testSource等。而Maven在设计之初的理念就是Conversion over configuration(约定大于配置)。其制定了一套项目目录结构作为标准的Java项目结构。一个典型的Maven项目结构如下:

    Gradle也沿用了这一标准的目录结构。如果你在Gradle项目中使用了标准的Maven项目结构的话,那么在Gradle中也无需进行多余的配置,只需在文件中包含apply plugin:’java’,系统会自动识别source、resource、test srouce、 test resource等相应资源。不过Gradle作为JVM上的构建工具,也同时支持groovy、scala等源代码的构建,甚至支持Java、groovy、scala语言的混合构建。虽然Maven通过一些插件(比如maven-scala-plugin)也能达到相同目的,但配置方面显然Gradle要更优雅一些。

    一致的构建模型
    为了解决Ant中对项目构建活动缺乏标准化的问题,Maven特意设置了标准的项目构建周期,其默认的构建周期如下所示:

    <phases>
     <phase>validate</phase>
     <phase>initialize</phase>
     <phase>generate-sources</phase>
     <phase>process-sources</phase>
     <phase>generate-resources</phase>
     <phase>process-resources</phase>
     <phase>compile</phase>
     <phase>process-classes</phase>
     <phase>generate-test-sources</phase>
     <phase>process-test-sources</phase>
     <phase>generate-test-resources</phase>
     <phase>process-test-resources</phase>
     <phase>test-compile</phase>
     <phase>process-test-classes</phase>
     <phase>test</phase>
     <phase>prepare-package</phase>
     <phase>package</phase>
     <phase>pre-integration-test</phase>
     <phase>integration-test</phase>
     <phase>post-integration-test</phase>
     <phase>verify</phase>
     <phase>install</phase>
     <phase>deploy</phase>
    </phases>
    

    插件机制

    Maven和Gradle设计时都采用了插件机制。但显然Gradle更胜一筹。主要原因在于Maven是基于XML进行配置。所以其配置语法太受限于XML。即使实现很小的功能都需要设计一个插件,建立其与XML配置的关联。比如想在Maven中执行一条shell命令,其配置如下:

    <plugin>
     <groupId>org.codehaus.mojo</groupId>
     <artifactId>exec-maven-plugin</artifactId>
     <version>1.2</version>
     <executions>
     <execution>
     <id>drop DB => db_name</id>
     <phase>pre-integration-test</phase>
     <goals>
     <goal>exec</goal>
     </goals>
     <configuration>
     <executable>curl</executable>
     <arguments>
     <argument>-s</argument>
     <argument>-S</argument>
     <argument>-X</argument>
     <argument>DELETE</argument>
     <argument>http://${db.server}:${db.port}/db_name</argument>
     </arguments>
     </configuration>
     </execution>
     </executions>
    </plugin>
    

    而在Gradle中则一切变得非常简单。

    task dropDB(type: Exec) {
     commandLine ‘curl’,’-s’,’s’,’-x’,’DELETE’,"http://${db.server}:{db.port}/db_name"
    }
    

    在创建自定义插件方面,Maven和Gradle的机制都差不多,都是继承自插件基类,然后实现要求的方法。这里就不展开说明。

从以上五个方面可以看出Maven和Gradle的主要差异。Maven的设计核心Convention Over Configuration被Gradle更加发扬光大,而Gradle的配置即代码又超越了Maven。在Gradle中任何配置都可以作为代码被执行的,我们也可以随时使用已有的Ant脚本(Ant task是Gradle中的一等公民)、Java类库、Groovy类库来辅助完成构建任务的编写。 这种采用本身语言实现的DSL对本身语言项目进行构建管理的例子比比皆是。比如Rake和Ruby、Grunt和JavaScript、Sbt和Ruby……而Gradle之所以使用Groovy语言实现,是因为Groovy比Java语言更具表现力,其语法特性更丰富,又兼具函数式的特点。这几年兴起的语言(比如Scala、Go、Swift)都属于强类型的语言,兼具面向对象和函数式的特点。 最后想说的Gradle的命令行比Maven的要强大的多。以前写过一篇文章专门讲述了Gradle的命令行操作,详情请见Gradle命令行黑魔法

问题

什么是scope?

1、枚举各个属性值的含义
compile,缺省值,适用于所有阶段,会打包进项目。
provided,类似compile,期望JDK、容器或使用者会提供这个依赖。
runtime,只在运行时使用,如JDBC驱动,适用运行和测试阶段。
test,只在测试时使用,用于编译和运行测试代码。不会随项目发布。
system,类似provided,需要显式提供包含依赖的jar,Maven不会在Repository中查找它

gradle 的版本依赖怎么玩?

参考

https://www.cnblogs.com/lykbk/p/erwerwerwerwerwerwe.html

https://blog.csdn.net/zy103118/article/details/84442623

发布了33 篇原创文章 · 获赞 37 · 访问量 11万+

猜你喜欢

转载自blog.csdn.net/hagle_wang/article/details/105391250