Maven Or Gradle?究极实测对比,孰强孰弱一看便知!

我们习惯了使用Maven构建工具,现在市面上大多数也都是使用的Maven,但是Gradle的出现,究竟哪个更好用哪个更有优势呢?

下载安装与配置

maven官网:Maven官网

maven配置环境(MacOS系统):

// 输入命令
vim ~/.bash_profile

//打开后配置环境变量,点i为输入,复制下面两句,MAVEN_HOME,换成自己下载的路径
export MAVEN_HOME=/Users/…/apache-maven-3.6.3
export PATH=$PATH:$MAVEN_HOME/bin
//配置完毕后 esc + :wq 保存退出

//输入 使配置生效
source ~/.bash_profile

//测试是否成功,要先装好jdk哦
mvn -version或者 mvn -v

效果图:

在这里插入图片描述

Gradle官网:Gradle官网

gradle配置环境(MacOS系统):

// 输入命令
vim ~/.bash_profile

//打开后配置环境变量,点i为输入,复制下面两句,GRADLE_HOME,换成自己下载的路径
GRADLE_HOME=/users/.../gradle-7.0
export GRADLE_HOME
export PATH=$PATH:$GRADLE_HOME/bin
//配置完毕后 esc + :wq 保存退出

//输入 使配置生效
source ~/.bash_profile

//测试是否成功,要先装好jdk哦
gradle -version

效果图:

在这里插入图片描述

1.相同之处

a>工具的作用相同

都是项目管理工具,都可以解决构建管理、依赖管理问题、项目自动化打包部署等操作。

b>依赖管理思想相同

用GroupID(组id)、ArtifactID(项目id)和Version(版本号)配合为唯一标识一个依赖项。

c>存储仓库思想相同

远程中央仓库(世界公用)、本地仓库(本地计算机上可创建)和私服(公司搭建的仓库)。

d>多模块构建思想相同

都可以对整个项目或其中特定子项目中进行配置。

e>项目目录结构相同

source、resource、test source、test resource等相应资源的标准结构。

普通java项目:如图

在这里插入图片描述

web项目:如图
在这里插入图片描述

2.不同之处

a>诞生时间,诞生原因不同

Maven于2004年诞生,而Gradle于2012年。

Maven出现是为了解决2000年诞生的项目构建工具:Ant存在的问题

而Gradle出现也是为了解决Maven存在的问题。

b>项目构建方式不同

maven使用xml文件配置项目,可以做到各种提供的配置选择,比如自动化编译、打包、部署,运行,但是缺乏自定义的拓展性,而gradle使用build.gradle配置文件,可以使用特定脚本语言groove编写自定义脚本加入到自动化构建流程中。

在Maven中需要定义POM(Project Object Model)作为一组module的通用配置模型,常见pom.xml配置项:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
  
    <groupId>com.example</groupId>
    <artifactId>demo</artifactId>
    <version>0.0.1-SNAPSHOT</version>
  
    <name>mavenDemo</name>
    <description>mavenDemo project for Spring Boot</description>
    <properties>
        <java.version>1.8</java.version>
    </properties>
  
  <!-- 依赖 -->
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
      	...
    </dependencies>

  <!-- 插件 -->
    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <configuration>
                    <excludes>
                        <exclude>
                            <groupId>org.projectlombok</groupId>
                            <artifactId>lombok</artifactId>
                        </exclude>
                    </excludes>
                </configuration>
            </plugin>
          	...
        </plugins>
    </build>

</project>

Gradle在build.gradle文件中常见配置项:

group 'com.example'
version '0.0.1-SNAPSHOT'

apply plugin: 'java'
sourceCompatibility = 1.8

//配置仓库,可选择先后方法,如先使用本地仓库,如果没有则使用自定义路径仓库,如果还是没有则使用中央仓库
repositories {
    mavenLocal()
    maven { url "http://maven.ipo.com/nexus/content/groups/public/" }
    mavenCentral()
}
//依赖坐标
dependencies {
    def springVersion = "4.2.8.RELEASE"
    //Spring相关依赖依赖
    compile("org.springframework:spring-aop:$springVersion",
            "org.springframework:spring-orm:$springVersion"...)
    //日志相关依赖
    compile(//"commons-logging:commons-logging:1.2",
            "log4j:log4j:1.2.17")
}
//使用TestNG生成测试报告
test {
    useTestNG {
        //打印正在运行的单元测试及结果
        testLogging.events = ["failed", "passed", "skipped"]
        //打印失败日志到控制台
        testLogging.showStandardStreams = true
        //配置testng.xml文件位置
        suites(file("src/main/resources/qacontext/testng.xml"));
    }
    beforeTest { descriptor ->
        logger.lifecycle("Running test: " + descriptor)
    }
    onOutput { descriptor, event ->
        logger.lifecycle("Test: " + descriptor + " produced standard out/err: " + event.message)
    }
}

如果依赖的jar很多,是不是gardle看起来更加流畅。

c>配置细节不同

1.scoup依赖作用范围

在Maven中,一个依赖项有6种scope,分别是compile、provided、runtime、test、system、import。其中compile为默认。而gradle将其简化为4种,compile、runtime、testCompile、testRuntime。

2.动态依赖版本

如代码“testCompile ‘junit:junit:4.+’”,在Gradle中支持动态的版本依赖,在版本号后面使用+号可以实现动态的版本管理。

3.多模块依赖、配置继承

Maven中需要定义parent POM(Project Object Model)作为一组module的通用配置模型,在POM文件中可以使用标签来定义一组子模块。parent POM中的build配置以及依赖配置会自动继承给子module。

如:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>org.example</groupId>
    <artifactId>demo_parent</artifactId>
    <packaging>pom</packaging>
    <version>1.0-SNAPSHOT</version>
    <modules>
        <module>demo_eureka</module>
        <module>demo_gateway</module>
        <module>demo_service</module>
        <module>demo_service_api</module>
        <module>demo_web</module>
        <module>demo_common</module>
		<module>demo_canal</module>
    </modules>

    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>Greenwich.SR1</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>

</project>

Gradle中,需要在parent的build.gradle中使用allprojects和subprojects代码块分别定义应用于所有项目或子项目中的配置。对于子模块中的定义放置在settings.gradle文件中,每一个模块代表project的对象实例。

如父项目使用allprojects方法自动继承给子项目:

在这里插入图片描述

在setting.settings.gradle中配置父项目和所有的子项目关系:

在这里插入图片描述

4.插件管理

build.gradle可以使用groove语言自定义编写插件、脚本加入到构建流程中。

简单例子,比如我们要在编译所有项目之前需要在控制台打印输出一下所编译的项目的项目名称和版本号:未完待续//todo

c>构建速度比较

我们对于同一个项目使用不同的构建工具,一起来测试一下相同操作的的时间。

我简单写了几个.java源码,maven项目和gradle项目代码、目录结构、依赖坐标都相同。我们对同一种操作多次尝试运行–

1.clean

Maven:125ms

在这里插入图片描述

Gradle:25ms

在这里插入图片描述

2.compile

Maven:450ms

在这里插入图片描述

Gradle:34ms

在这里插入图片描述

3.Test

Maven:739ms

在这里插入图片描述

Gradle:325ms

在这里插入图片描述

4.install

Maven:885ms

在这里插入图片描述

Gradle:65ms

在这里插入图片描述

可见,这只是我随便添加了几个java文件,如果是企业级的项目,差距应该会更大。

d>执行原理不同

他们虽然都是使用Java开发的工具,但为什么Gradle的速度更快呢?因为执行原理不同,因为Maven和Gradle核心代码都是用Java语言编写的,所有他们执行任何任务(Lifecycle)都是启动一个JVM进程。一个JVM的启动是很慢,因为需要加载所有的jar包,但是区别:

Maven:要执行一个任务(如compile),需要启动一个JVM进程,任务完成后,JVM进程销毁。

Gradle:要执行一个任务(如compile),首先会启动一个ClientJVM,它非常轻量,负责接收、转发请求,只去后台链接称为DaemonJVM通信,把任务和参数发送给Daemon,Daemon执行结束后,结果返回给ClientJvm。然后ClientJVM被销毁,而Daemon则会一直存在,默认存在3小时,如果需要多次运行,只需要第一次预热,减少了启动开销。如图:
在这里插入图片描述

另外:

gradle在多个版本的同一个类型jar包选择中,如果有版本高的,他会默认选择最高版本的jar,可能会出现间接依赖的高版本的包,并不是你想要的,所以会出现编译报错哦。
解决方案,使用force=true,来强制指定某个版本的jar包。

Logo

开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!

更多推荐