Gradle最佳实践 精华

发布于 2021-1-13 14:03
736浏览
0收藏

一、Gradle相比Maven的优势


    1.配置简洁

 

        Maven是用pom.xml管理,引入一个jar包至少5行代码,Gradle只需要一行。


    2.构建速度快

 

        Gradle支持daemon方式运行,启动速度快,同时有基于daemon的增量构建,充分利用JVM的运行时优化,和缓存数据构建速度相比Maven快很多。

 

    3.更好的灵活性、扩展性

 

        Gradle 相对于 Maven 等构建工具, 其提供了一系列的 API 让我们有能力去修改或定制项目的构建过程。


二、基本配置


    1.设置本地仓库地址

 

        默认本地仓库地址是:~/.gradle,Windows下会占用大量C盘空间。

        设置环境变量,GRADLE_USER_HOME=/your/path


    2.复用Maven本地仓库

        在repositories配置mavenLocal()即可,如果是init.gradle全局配置,参考以下init.gradle文件

        Maven本地仓库查找路径:

        (1)USER_HOME/.m2/settings.xml

        (2)M2_HOME/conf/settings.xml

        (3)USER_HOME/.m2/repository


    3.国内镜像加速

        国内访问国外仓库地址很慢,第一种方法是在每个项目中设置repositories

repositories {
    mavenLocal()
    'maven(http://maven.aliyun.com/nexus/content/groups/public/)'
    mavenCentral()
}

更推荐的方式是类似的Maven的settings.xml全局的配置,在上一步配置的GRADLE_USER_HOME路径下,添加init.gradle文件,以下配置文件中使用了阿里云的Gradle代理,支持jcenter、google、maven仓库。

gradle.projectsLoaded {
    rootProject.allprojects {
        buildscript {
            repositories {
                def JCENTER_URL = 'https://maven.aliyun.com/repository/jcenter'
                def GOOGLE_URL = 'https://maven.aliyun.com/repository/google'
                def NEXUS_URL = 'http://maven.aliyun.com/nexus/content/repositories/jcenter'
                all { ArtifactRepository repo ->
                    if (repo instanceof MavenArtifactRepository) {
                        def url = repo.url.toString()
                        if (url.startsWith('https://jcenter.bintray.com/')) {
                            project.logger.lifecycle "Repository ${repo.url} replaced by $JCENTER_URL."
                            println("buildscript ${repo.url} replaced by $JCENTER_URL.")
                            remove repo
                        }
                        else if (url.startsWith('https://dl.google.com/dl/android/maven2/')) {
                            project.logger.lifecycle "Repository ${repo.url} replaced by $GOOGLE_URL."
                            println("buildscript ${repo.url} replaced by $GOOGLE_URL.")
                            remove repo
                        }
                        else if (url.startsWith('https://repo1.maven.org/maven2')) {
                            project.logger.lifecycle "Repository ${repo.url} replaced by $REPOSITORY_URL."
                            println("buildscript ${repo.url} replaced by $REPOSITORY_URL.")
                            remove repo
                        }
                    }
                }
                jcenter {
                    url JCENTER_URL
                }
                google {
                    url GOOGLE_URL
                }
                maven {
                    url NEXUS_URL
                }
            }
        }
        repositories {
            def JCENTER_URL = 'https://maven.aliyun.com/repository/jcenter'
            def GOOGLE_URL = 'https://maven.aliyun.com/repository/google'
            def NEXUS_URL = 'http://maven.aliyun.com/nexus/content/repositories/jcenter'
            all { ArtifactRepository repo ->
                if (repo instanceof MavenArtifactRepository) {
                    def url = repo.url.toString()
                    if (url.startsWith('https://jcenter.bintray.com/')) {
                        project.logger.lifecycle "Repository ${repo.url} replaced by $JCENTER_URL."
                        println("buildscript ${repo.url} replaced by $JCENTER_URL.")
                        remove repo
                    }
                    else if (url.startsWith('https://dl.google.com/dl/android/maven2/')) {
                        project.logger.lifecycle "Repository ${repo.url} replaced by $GOOGLE_URL."
                        println("buildscript ${repo.url} replaced by $GOOGLE_URL.")
                        remove repo
                    }
                    else if (url.startsWith('https://repo1.maven.org/maven2')) {
                        project.logger.lifecycle "Repository ${repo.url} replaced by $REPOSITORY_URL."
                        println("buildscript ${repo.url} replaced by $REPOSITORY_URL.")
                        remove repo
                    }
                }
            }
            jcenter {
                url JCENTER_URL
            }
            google {
                url GOOGLE_URL
            }
            maven {
                url NEXUS_URL
            }
        }
    }
}

三、最佳实践
    1.多模块配置

 

        稍微大点的项目都会分模块开发,Gradle相比Maven的一个优势是用IDEA执行一个项目的代码时,会自动编译其依赖的其他模块。

 

        在项目一级目录下添加settings.gradle配置文件:

rootProject.name = 'my-roject-name'

include 'module1'
include 'module2'

其中module1、module2就是子模块的文件夹名,在子模块里需要有一个配置子模块的build.gradle

 

模块内依赖,比如module2依赖module1,在module2的build.gradle配置文件里添加:

dependencies {
    compile project(":module1")
}

2.profile支持

 

        profile用来加载不同环境的的配置文件,在笔者所在公司,推荐dev、test、staging、prod四套环境。

 

        添加gradle.properties配置文件指定默认profile

profile=dev

启动profile,加载不同路径下的配置,在build.gradle里添加配置:

ext {
    profile = project['profile']
}
sourceSets {
    main {
        resources {
            srcDirs = ["src/main/resources/", "src/main/profiles/${profile}"]
        }
    }
}

命令行参数指定profile:

gradle build -Pprofile=prod

3.初始化gradle项目

 

安装gradle,并在项目顶级目录下执行:

gradle init

如果当前目录有pom.xml,接下来会提示是否从Maven项目初始化Gradle项目,选择yes回车执行。

参数文档:https://docs.gradle.org/current/userguide/build_init_plugin.html

 

4.引入bom文件

 

pom文件在Maven中是一个很有用的功能,方便多个项目统一版本号,在Maven中配置方式如下:

<dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-dependencies</artifactId>
                <version>${spring-boot.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
</dependencyManagement>

Gradle有插件支持类似操作:

//引入插件
plugins {
    id "io.spring.dependency-management" version "1.0.10.RELEASE"
}
//引入bom
dependencyManagement {
    imports {
        mavenBom 'org.springframework.boot:spring-boot-dependencies:${spring-boot.version}'
    }
}
//使用bom,不需要执行版本号
dependencies {
    implementation "org.springframework.boot:spring-boot-starter-web"
}

5.引入parent文件

 

    在maven中执行parent是管理多个项目常用的方式,parent指定了项目的基本配置,配置方式如下:

<parent>
  <groupId>com.lesofn.blog</groupId>
  <artifactId>test-parent</artifactId>
  <version>0.0.1</version>
</parent>

        Maven中的parent有两个作用,一个是类似bom的统一管理版本,即parent中的:dependencyManagement,另一个是基础jar包的引用,即父pom中的:dependencies

 

        在Gradle可通过上面的io.spring.dependency-management插件实现类似的效果:

//引入插件
plugins {
    id "io.spring.dependency-management" version "1.0.10.RELEASE"
}
//引入parent,实现maven中dependencyManagement的功能,不用指定版本号
dependencyManagement {
    imports {
        mavenBom 'com.lesofn.blog:test-parent:0.0.1'
    }
}
//再次引入parent,实现maven中dependencies的功能
dependencies {
    implementation 'com.lesofn.blog:test-parent:0.0.1'
}

四、总结


经过以上配置,基本覆盖了Gradle开发过程中的大部分问题,如果还有什么问题,欢迎留言讨论。

 

本文作者:木小丰,美团Java高级工程师,关注架构、软件工程、全栈等,不定期分享软件研发过程中的实践、思考。

已于2021-1-13 14:06:50修改
1
收藏
回复
举报
回复
上传资源包
上传文件可以提高自己的声望,一次最多可上传5个文件 查看上传规则
    这个用户很懒,还没有个人简介
    帖子
    视频
    声望
    粉丝
    社区精华内容