是时候放弃Maven,拥抱Gradle了!

maven已经满足了开发人员百分之九十九的需求,为什么还要用gradle?

因为我们是技术人。

在开始装逼之前,放一张spring官方的消息图:

在这里插入图片描述
上面这位Andy Wilkinson是springboot团队大佬,他在六月8号发布了一条推文,大致意思是:在Springboot2.3版本之后,我们将构建工具从maven迁移到gradle上,如果您对我们进行更改的原因和方式感兴趣,我刚刚发布了一篇博客文章,其中包含一些详细信息:why gradle逐步构建……。现在,平均而言,CI构建速度提高了3到4倍,本地构建速度提高了20到30倍…… 正如评论区中的大佬发言, 构建速度是第一要义,在这一点上,似乎Gradle完爆了maven,究竟gradle是何方神圣,在下面我们会从几个方面和通过一个简单的项目改造来聊一聊这个java世界构建工具的翘楚。

灵活性

Google选择Gradle作为Android的官方构建工具 ; 不是因为构建脚本是代码,而是因为Gradle的建模方式可以用最基本的方式扩展。Gradle的模型还允许将其用于C / C ++的本机开发,并且可以扩展为涵盖任何生态系统。例如,Gradle在使用Tooling API的时候就考虑了嵌入。

Gradle和Maven都提供了配置约定。但是,Maven提供了一个非常僵化的模型,使定制变得乏味,有时甚至是不可能的。尽管这可以使您更容易理解任何给定的Maven构建,但是只要你没有任何特殊要求,它也就不适合许多自动化问题。另一方面,Gradle的构建考虑了授权和负责任的用户。

性能

缩短构建时间是加快项目产出的最直接方法之一。Gradle和Maven都采用某种形式的并行项目构建和并行依赖项解析。最大的不同是Gradle避免工作和增加工作量的机制。使Gradle比Maven快得多的前3个功能是:

  • 增量 — Gradle通过跟踪任务的输入和输出并仅运行必要的内容,并且仅在可能时处理已更改的文件,从而避免了工作。
  • Build Cache(构建缓存) —重用具有相同输入的任何其他Gradle构建的构建输出,包括在机器之间。
  • Gradle Daemon —一个长期存在的过程,可将构建信息“热”存储在内存中。

在Gradle与Maven的性能对比中,这些和更多的性能功能使Gradle在几乎每种情况下的速度至少是其两倍(对于使用构建缓存的大型构建而言,则要快100倍)。

注意: Gradle和Maven用户都可以利用Gradle Enterprise中可用的Build Cache技术。Gradle用户通常可将构建时间减少约50%,而Maven用户通常可将构建时间减少约90%

就减少项目的构建时间而言,Springboot将构建迁移到Gradle无疑是成功的。如上所述,在CI和开发人员自己的计算机上,基于Maven的完整构建都需要一个小时或更长时间。在过去的四个星期中,Gradle的平均成功构建时间为9分22秒,如以下屏幕截图所示:

在这里插入图片描述

依赖管理

两种构建系统都提供了内置功能,可以解决可配置存储库中的依赖项。两者都可以在本地缓存依赖项并并行下载它们。

作为库使用者,Maven允许重写一个依赖项,但只能按版本。Gradle提供了可自定义的依赖关系选择和替换规则,这些规则可以声明一次,并在项目范围内处理不需要的依赖关系。这种替换机制使Gradle可以一起构建多个源项目以创建复合构建。

Maven具有很少的内置依赖项作用域,这些作用域在常见的情况下(例如使用测试夹具或代码生成)强制使用笨拙的模块体系结构。例如,单元测试和集成测试之间没有分隔。Gradle允许自定义依赖项范围,它提供了更好的建模和更快的构建。

Maven依赖关系冲突解决方案的工作路径最短,这受声明顺序影响。Gradle解决了所有冲突,选择了图中最高版本的依赖项。此外,使用Gradle可以将版本声明为严格,这使它们可以优先于传递版本,从而可以降级依赖项。

作为库生产者,Gradle允许生产者声明“ api”和“ implementation”依赖项,以防止有害的库泄漏到使用者的类路径中。Maven允许发布者通过可选的依赖项提供元数据,但仅作为文档提供。Gradle完全支持功能变体和可选依赖项。
单从依赖写法上来说,Gradle的Groovy DSL较与xml的maven,更为java开发人员所喜爱,例如以下为我一个多模块分布式项目的父pom:

<?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>
    <packaging>pom</packaging>
    <modules>
        <module>editor-common</module>
        <module>editor-api</module>
        <module>editor-service</module>
    </modules>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.3.1.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.onesports.editor</groupId>
    <artifactId>odf-editor-system</artifactId>
    <version>1.0.0-SNAPSHOT</version>
    <description>一体ODF模板编辑器平台</description>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
        <java.version>1.8</java.version>
        <maven.compiler.source>1.8</maven.compiler.source>
        <maven.compiler.target>1.8</maven.compiler.target>
        <mybatis.plus.version>3.3.1</mybatis.plus.version>
        <lombok.version>1.16.10</lombok.version>
        <fast.json>1.2.72</fast.json>
        <hu.tool.version>5.3.9</hu.tool.version>
        <mysql.version>5.1.47</mysql.version>
        <druid.version>1.1.21</druid.version>
        <knife4j.version>1.0.4.RELEASE</knife4j.version>
        <beetl.version>3.1.7.RELEASE</beetl.version>
        <jwt.version>3.5.0</jwt.version>
        <validator.version>6.0.13.Final</validator.version>
        <ftp.version>0.1.51</ftp.version>
        <h2.version>1.4.200</h2.version>
    </properties>

    <developers>
        <developer>
            <name>xiejiarong</name>
            <email>937890254@qq.com</email>
            <url>https://gitee.com/sophis/odf-editor</url>
        </developer>
    </developers>





    <dependencies>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>${lombok.version}</version>
        </dependency>
        <dependency>
            <groupId>com.gitee.sophis</groupId>
            <artifactId>spring-boot-knif4j-starter</artifactId>
            <version>${knife4j.version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>
    <dependencyManagement>
        <!-- 轻巧工具类-->
        <dependencies>
            <!-- JWT鉴权工具-->
            <dependency>
                <groupId>com.auth0</groupId>
                <artifactId>java-jwt</artifactId>
                <version>${jwt.version}</version>
            </dependency>
            <!-- beetl模板-->
            <dependency>
                <groupId>com.ibeetl</groupId>
                <artifactId>beetl</artifactId>
                <version>${beetl.version}</version>
            </dependency>
            <dependency>
                <groupId>cn.hutool</groupId>
                <artifactId>hutool-all</artifactId>
               <version>${hu.tool.version}</version>
            </dependency>

            <dependency>
                <groupId>com.gitee.sophis</groupId>
                <artifactId>spring-boot-knif4j-starter</artifactId>
                <version>${knife4j.version}</version>
            </dependency>
            <!--  解析xml -->
            <dependency>
                <groupId>org.dom4j</groupId>
                <artifactId>dom4j</artifactId>
                <version>2.0.0</version>
            </dependency>

            <!-- 数据库-->
            <dependency>
                <groupId>com.alibaba</groupId>
                <artifactId>fastjson</artifactId>
                <version>${fast.json}</version>
            </dependency>
            <dependency>
                <groupId>com.h2database</groupId>
                <artifactId>h2</artifactId>
                <scope>runtime</scope>
                <version>${h2.version}</version>
            </dependency>

            <dependency>
                <groupId>com.alibaba</groupId>
                <artifactId>druid-spring-boot-starter</artifactId>
                <version>${druid.version}</version>
            </dependency>
            <!--mybatis plus -->
            <dependency>
                <groupId>com.baomidou</groupId>
                <artifactId>mybatis-plus-boot-starter</artifactId>
                <version>${mybatis.plus.version}</version>
            </dependency>
            <!-- 表单校验-->
            <dependency>
                <groupId>org.hibernate</groupId>
                <artifactId>hibernate-validator</artifactId>
                <version>${validator.version}</version>
            </dependency>
            <!-- ftp-->
            <dependency>
                <groupId>com.jcraft</groupId>
                <artifactId>jsch</artifactId>
                <version>${ftp.version}</version>
            </dependency>

        </dependencies>
    </dependencyManagement>




    <build>
        <plugins>
            <!-- Compiler 插件, 设定 JDK 版本 -->
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <configuration>
                    <showWarnings>true</showWarnings>
                </configuration>
            </plugin>

            <!-- 打包 jar 文件时,配置 manifest 文件,加入 lib 包的 jar 依赖 -->
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-jar-plugin</artifactId>
                <configuration>
                    <archive>
                        <addMavenDescriptor>false</addMavenDescriptor>
                    </archive>
                </configuration>
                <executions>
                    <execution>
                        <configuration>
                            <archive>
                                <manifest>
                                    <!-- Add directory entries -->
                                    <addDefaultImplementationEntries>true</addDefaultImplementationEntries>
                                    <addDefaultSpecificationEntries>true</addDefaultSpecificationEntries>
                                    <addClasspath>true</addClasspath>
                                </manifest>
                            </archive>
                        </configuration>
                    </execution>
                </executions>
            </plugin>

            <!-- resource -->
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-resources-plugin</artifactId>
            </plugin>

            <!-- install -->
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-install-plugin</artifactId>
            </plugin>

            <!-- clean -->
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-clean-plugin</artifactId>
            </plugin>

            <!-- ant -->
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-antrun-plugin</artifactId>
            </plugin>

            <!-- dependency -->
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-dependency-plugin</artifactId>
            </plugin>
        </plugins>

        <pluginManagement>
            <plugins>
                <!-- Java Document Generate -->
                <plugin>
                    <groupId>org.apache.maven.plugins</groupId>
                    <artifactId>maven-javadoc-plugin</artifactId>
                    <executions>
                        <execution>
                            <phase>prepare-package</phase>
                            <goals>
                                <goal>jar</goal>
                            </goals>
                        </execution>
                    </executions>
                </plugin>

                <!-- YUI Compressor (CSS/JS压缩) -->
                <plugin>
                    <groupId>net.alchim31.maven</groupId>
                    <artifactId>yuicompressor-maven-plugin</artifactId>
                    <version>1.5.1</version>
                    <executions>
                        <execution>
                            <phase>prepare-package</phase>
                            <goals>
                                <goal>compress</goal>
                            </goals>
                        </execution>
                    </executions>
                    <configuration>
                        <encoding>UTF-8</encoding>
                        <jswarn>false</jswarn>
                        <nosuffix>true</nosuffix>
                        <linebreakpos>30000</linebreakpos>
                        <force>true</force>
                        <includes>
                            <include>**/*.js</include>
                            <include>**/*.css</include>
                        </includes>
                        <excludes>
                            <exclude>**/*.min.js</exclude>
                            <exclude>**/*.min.css</exclude>
                        </excludes>
                    </configuration>
                </plugin>
            </plugins>
        </pluginManagement>

        <!-- 资源文件配置 -->
        <resources>
            <resource>
                <directory>src/main/java</directory>
                <excludes>
                    <exclude>**/*.java</exclude>
                </excludes>
            </resource>
            <resource>
                <directory>src/main/resources</directory>
            </resource>
        </resources>
    </build>
</project>

而在前几天我成功将其迁移到gradle时,它的写法变成这样子:

/*
 * This file was generated by the Gradle 'init' task.
 */

apply from:  "version.gradle"

buildscript {
    ext {
        springBootVersion = '2.3.1.RELEASE'
        dependencyManagementPluginVersion = '1.0.10.RELEASE'
    }
    repositories {
        maven { url 'http://maven.aliyun.com/nexus/content/groups/public/' }
    }
    dependencies {
        classpath("org.springframework.boot:spring-boot-gradle-plugin:${springBootVersion}")
        classpath("io.spring.gradle:dependency-management-plugin:${dependencyManagementPluginVersion}")
    }
}

allprojects {
    group = 'com.onesports.editor'
    version = '1.0.0-SNAPSHOT'

    apply plugin: 'java'
    apply plugin: 'idea'

    sourceCompatibility = '1.8'
    targetCompatibility = '1.8'

    [compileJava, compileTestJava, javadoc]*.options*.encoding = 'UTF-8'
// 编译字符集
    tasks.withType(JavaCompile) { options.encoding = 'utf-8' }
}

subprojects {
    apply plugin: 'io.spring.dependency-management'
//    apply plugin: 'org.springframework.boot'

    dependencyManagement {
        imports {
            mavenBom("org.springframework.boot:spring-boot-dependencies:${springBootVersion}")
        }
    }
    repositories {
        mavenLocal()
        maven { url 'http://maven.aliyun.com/nexus/content/groups/public/' }
        mavenCentral()
    }

    dependencies {
        compileOnly 'org.projectlombok:lombok:1.16.10'
        annotationProcessor 'org.projectlombok:lombok:1.16.10'
        compile 'com.gitee.sophis:spring-boot-knif4j-starter:1.0.7.RELEASE'
        testImplementation 'org.springframework.boot:spring-boot-starter-test:2.3.1.RELEASE'
    }

}

单纯从代码量上来说,gradle会比maven的配置少很多,而且从语法上来讲,Groovy DSL更容易理解和拓展,写起来非常爽!

制品发布

喜欢开源的朋友,可能经常会利用maven发布自己的开源工具包到网上供其他人使用,在发布这一项上maven扳回一城,Maven原生支持maven jar的格式,发布很简单;而Gradle虽说既支持Maven又支持Gradle,但是就要我们自己做很多额外的工作。比如Maven要发布制品,只需要配置远程仓库的参数:

 <distributionManagement>
    <repository>
      <id>internal</id>
      <name>Internal Release Repository</name>
      <url>http://repository.springsource.com/maven/bundles/release</url>
    </repository>
  </distributionManagement>

而gradle发布制品,还需要生成pom文件:

uploadArchives {
    repositories {
        mavenDeployer {
            //为Pom文件做数字签名
            beforeDeployment { MavenDeployment deployment -> signing.signPom(deployment) }

            repository(url: "http://repository.springsource.com/maven/bundles/release") {
                authentication(userName: username, password: password)
            }
            //构造项目的Pom文件
            pom.project {
                name project.name
                packaging 'jar'
                description 'description'

            }
        }
    }
}

一定要使用Gradle?

其实,Gradle较于maven,相当于mybatis-plus较于mybatis, 同样的工具,有增强的地方,但是不代表新的就是好的,maven虽然配置比较冗长,但是发展了这么多年,目前非常多的开源项目和IDE对maven的支持度绝对是高于gradle的,合适自己的才是好的,只是作为一个技术人的角度来说,why not have a try? 稳定好用绝对不是我们原地踏步、不愿迈出舒适圈的理由,作为一个程序开发人员,应该有一定的猎奇心理和探索精神,而且学习Gradle对于Android的学习也是有一定的帮助,毕竟谷歌公司官方指定的安卓构建工具。

总结

如果你打算学习一下Gradle,那么恭喜你又学会了一门构建工具的使用和脚本语言;如果你是快乐的maven使用者,那么请继续支持对你有用有效的构建工具。

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值