Gradle 学习笔记

 

建议关键字: gradle Groovy 构建工具 build tools

0x01 简介

omitted…

0x02 安装

官网地址:https://gradle.org/

配置环境变量 GRADLE_HOME,添加到 PATH

验证:

$ echo $GRADLE_HOME
/Users/chengchao/apps/gradle
$ gradle -v

Welcome to Gradle 7.5.1!

Here are the highlights of this release:
 - Support for Java 18
 - Support for building with Groovy 4
 - Much more responsive continuous builds
 - Improved diagnostics for dependency resolution

For more details see https://docs.gradle.org/7.5.1/release-notes.html


------------------------------------------------------------
Gradle 7.5.1
------------------------------------------------------------

Build time:   2022-08-05 21:17:56 UTC
Revision:     d1daa0cbf1a0103000b71484e1dbfe096e095918

Kotlin:       1.6.21
Groovy:       3.0.10
Ant:          Apache Ant(TM) version 1.10.11 compiled on July 10 2021
JVM:          17 (Oracle Corporation 17+35-LTS-2724)
OS:           Mac OS X 12.6.1 x86_64

0x03 了解 Groovy

Groovy 是基于 Java 虚拟机的一种动态语言。Gradle 使用 Groovy 构建和管理的。

  • 分号是可选的
  • 类/方法牧人是 public 的
  • 自动给属性添加 getter/setter 方法
  • 属性可以直接使用 . 号获取
  • 方法中最后一个表达式的值会作为返回值返回
  • == 等同于 equals(),不回有空指针异常
  • 可选类型定义,类型自动推倒出来
  • 自带 assert 语句
  • 可选的括号,没有参数的话,方法可以不写括号
  • 字符串可用单引号/双引号/三个双引号
  • 集合 API
  • 闭包

Grovvy 简单示例

class ProjectVersion {

    private int major;
    private int minor;

    ProjectVersion(int major, int minor) {
        this.major = major
        this.minor = minor
    }

    int getMajor() {
        major
    }

    void setMajor(int major) {
        this.major = major
    }
}

ProjectVersion v1 = new ProjectVersion(1, 1)

println v1.minor

ProjectVersion v2 = null

println("v2 == v1 : " + (v2 == v1))

// 1, 可选的类型定义
def version = 1

// 2, assert
assert version == 1

// 3, 括号可选
println("version => " + version)
println "version = " + version

// assert version == 2

// 4, 字符串
def s1 = 'imooc'
def s2 = "gradle version is ${version}"
def s3 = """my
name is 
chengchaos 
"""

println s1
println s2
println s3

// 5, 集合 API
// list
def buildTools = ['ant', 'maven']
buildTools << 'gradle'

assert buildTools.getClass() == ArrayList
assert buildTools.size() == 3

// map

def buildYears = ['ant': 2000, 'maven': 2004]
buildYears.gradle = 2009
println buildYears.ant
println buildYears['gradle']

println buildYears.getClass()

// 闭包
def Closure c1 = { v ->
    println(v)
}

def c2 = {
    println "hello"
}

def static method1(Closure closure) {
    closure('param')
}

def static method2(Closure closure) {
    closure()
}

method1(c1)
method2(c2)

构建脚本示例

// 构建脚本中默认是都有个 Project 的实例
// Project 实例中有个 apply 方法,
// 方法的命名参数 plugin 的值为 java
apply plugin:'java'

// Project 有个属性叫 version 。
version= '0.1'


// repositories 同样也是 Project 的一个方法
// 使用 Closure 作为参数
repositories {
  mavenCentral() // 闭包
}

// 同样是一个方法, 同样是用 Closure 作为参数
dependencies {
  compile 'commons-codec:commons-codec:1.6'
}

0x04 简单 Gradle 项目示例

build.gradle


// 构建脚本中默认是都有个 Project 的实例
plugins {
    id 'java'
}

group 'c.b.cheng'
version '1.0-SNAPSHOT'

sourceCompatibility = 17
targetCompatibility = 17

// create a single jar with all dependencies
task fatJar(type: Jar) {
    manifest {
        attributes 'Implementation-Title': 'Gradle Jar File Example',
                'Implementation-Version': archiveVersion,
                'Main-Class': 'c.b.cheng.example.Demo'
    }
    archiveBaseName = project.name + '-all'
    from {
        duplicatesStrategy = DuplicatesStrategy.EXCLUDE
        configurations.runtimeClasspath.findAll {
            // 打包所有依赖的 jar
            it.name.endsWith('.jar')
        }.collect {
            println 'add ' + it.name
            zipTree(it)
        }
    }
    with jar
}


repositories {
    mavenCentral()
}

dependencies {
    testImplementation 'org.junit.jupiter:junit-jupiter-api:5.9.0// '
    testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine:5.9.0'

    // https://mvnrepository.com/artifact/ch.qos.logback/logback-classic
    // implementation group: 'ch.qos.logback', name: 'logback-classic', version: '1.4.4'
    // https://mvnrepository.com/artifact/ch.qos.logback/logback-classic
    implementation 'ch.qos.logback:logback-classic:1.4.4'

}

test {
    useJUnitPlatform()
}


0x05 Gradle 简单使用

几个基本概念

Project 项目

一个项目代表一个正在构建的组件,当构建启动后,Gradle 会基于 build.gradle 实例化一个 org.gradle.api.Project 类对象,并且能够通过 project 变量使其隐式可用。

常见的属性:

  • group
  • name
  • version

常见的方法:

  • apply // 应用一个插件
  • dependencies // 声明依赖哪些 jar
  • repositories // 声明哪些仓库
  • task // 声明项目中的任务

属性的其他配置方式:

  • ext
  • gradle.properties

Task 任务

Task 对应 org.gradle.api.Task 类。主要包括任务动作和任务依赖。任务动作定义了一个最小的工作单元。可以定义依赖于其他任务、动作序列和执行条件。

任务中的方法:

  • dependsOn // 定义任务依赖
  • doFirst // 在动作列表前边添加一个动作
  • doLast / « // 在动作列表末尾添加一个动作

0x06 自定义任务

def createDir = {
  path -> 
  File dir = new File(path)
  if (!dir.exists()) {
    dir.mkdirs()
  }
}
task makeJavaDir() {
  def paths = ['src/test/java', 'src/test/resources']
  doFirst{
    paths.forEach(createDir)
  }
}

0x07 构建的生命周期

  • 初始化 // 初始化任务
  • 配置 // 生成 task 的依赖顺序
  • 执行 //

0x08 依赖管理

常用仓库:

  • mavenLocal // 本机
  • mavenCentral
  • jcenter
  • 自定义 maven 仓库
  • 文件仓库 // 本地机器上的文件路径

使用阿里云镜像

对单个项目生效,在项目中的build.gradle修改内容

buildscript {
    repositories {
        maven {
            url 'https://maven.aliyun.com/nexus/content/groups/public/'
        }
        maven {
            url 'https://maven.aliyun.com/nexus/content/repositories/jcenter'
        }
    }
}

allprojects {
    repositories {
        maven {
            url 'https://maven.aliyun.com/nexus/content/groups/public/'
        }
        maven {
            url 'https://maven.aliyun.com/nexus/content/repositories/jcenter'
        }
    }
}

对所有项目生效,在 USER_HOME/.gradle/ 下创建 init.gradle 文件

allprojects {
    repositories {
        def ALIYUN_REPOSITORY_URL = 'https://maven.aliyun.com/nexus/content/groups/public'
        def ALIYUN_JCENTER_URL = 'https://maven.aliyun.com/nexus/content/repositories/jcenter'
        all {
            ArtifactRepository repo ->
                if (repo instanceof MavenArtifactRepository) {
                    def url = repo.url.toString()
                    if (url.startsWith('https://repo1.maven.org/maven2')) {
                        project.logger.lifecycle "Repository ${repo.url} replaced by $ALIYUN_REPOSITORY_URL."
                        remove repo
                    }
                    if (url.startsWith('https://jcenter.bintray.com/')) {
                        project.logger.lifecycle "Repository ${repo.url} replaced by $ALIYUN_JCENTER_URL."
                        remove repo
                    }
                }
        }
        maven {
            url ALIYUN_REPOSITORY_URL
            url ALIYUN_JCENTER_URL
        }
    }
}

0x09 管理依赖

通常的解决冲突的实现步骤:

  • 查看依赖报告
  • 排除传递性依赖
  • 强制使用一个版本

gradle 会帮助我们使用最高版本解决依赖冲突。

修改默认解决策略

configurations.all {
  resolutionStrategy {
    failOnVersionConflict()
  }
}

排出传递性依赖

compile('org.hibrenate:hibernate-core:3.6.3.Final') {
  exclude grouip: "org.slf4j", module: "slf4j-api"
  // transitive = false
}

强制指定一个版本

configurations.all {
  resolutionStrategy {
    force 'org.slf4j:slf4j-api:1.7.24'
  }
}

0x0a 多项目构建

omitted…and so forth.

参考链接

EOF