Gradle

官方文档:https://docs.gradle.org/current/userguide/userguide.html

Java三种构建工具比较

对比AntMavenGradle

构建性能

最高

最低

居中

仓库

开发者自己处理

maven仓库

支持各种仓库

依赖管理

ivy管理

GAV管理

GNV管理

插件支持

实现方便

实现较难

实现方便

遵循特定的目录结构

No

Yes

Yes

配置文件

xml文件(繁琐)

xml文件

代码脚本,便于写业务逻辑

侧重点

小型项目构建

项目包管理

大型项目构建

目前地位

使用较少

目前主流

未来趋势

项目的目录结构

Gradle指令

指令作用

gradle init

创建gradle项目

gradle init --type pom

将maven项目转换为gradle

gradle classes

编译源代码与配置文件

gradle test

编译测试代码,生成测试报告

gradle build

构建项目

gradle build -x test

构建项目,且跳过测试

gradle clean

清空build目录

init.gradle

~/.gradle/init.gradle是gradle的全局配置脚本,他有四种方式可以配置,优先级从高到低:

  1. 运行指令时指定初始化脚本:gradle -init-script yourdir/init.gradle -q taskName,也可以指定多个init文件

  2. $USER_HOME/.gradle/init.gradle文件

  3. $USER_HOME/.gradle/init.d/*.gradle多个文件

  4. $GRADLE_HOME/init.d/*.gradle多个文件

gradle会按照上述1-4的顺序依次执行这些文件,如果文件夹中包含多个脚本文件,则会按照字母顺序依次执行。

仓库说明

配置远程仓库地址:

// 所有项目的仓库配置,建议放在init.d目录下
allprojects {
    repositories {
        maven { url "https://maven.aliyun.com/repository/public" }
        mavenCentral() // 使用maven中央仓库
        mavenLocal() // 使用maven本地仓库
    }
}

Gradle下载的依赖的位置位于$USER_HOME/.gradle/caches,如果配置了$GRADLE_USER_HOME环境变量,将会放在该目录下的caches子目录下。

注意,不要将caches目录与MVN的本地仓库指向统一位置,因为caches下载文件与mvn仓库的存放方式不同。

Gradle Wrapper

Gradle Wrapper是对Gradle的一层包装,用于解决实际开发中不同项目需要不同版本的Gradle问题:

  1. 项目拉取者本地没有Gradle

  2. 项目拉去这本地Gradle版本与项目不一致

这个时候就需要gradle了。

Gradle Wrapper 提供了如下文件:

gradlew # *inx脚本,用于执行gradle命令
gradlew.bat # win脚本,用于执行gradle命令
gradle/gradle-wrapper.jar # gradle wrapper核心包,他会根据配置文件下载指定版本的gradle,然后使用
gradle/gradle-wrapper.properties # gradle wrapper的配置,比如可以配置目标gralde的版本

使用gradle修改gradle wrapper的信息

# 修改项目的gradle wrapper所使用的graldle的版本
gradle wrapper --gradle-versio7.4.2
参数说明

--gradle-version

用于指定使用Gradle版本

--gradle-distribution-url

用于指定下载gradle发行版本的url(原来的可能很慢)

直接修改配置文件修改gradle wrapper的信息

修改properties 文件即可:

distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-7.4-bin.zip
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists

Gradle Wrapper的执行流程

  1. 执行 ./gradlew build

  2. 读取 ./gradle/gradle-wrapper.properties配置文件

  3. 将配置文件中的指定版本的gradle下载到 $GRADLE_HOME/wrapper/dists目录下(如果已经有了将不会再下载了)

  4. 并构建本地缓存($GRADLE_HOME/caches

  5. 之后执行的所有的 .gradlew 命令实际都是调用的目标版本的gradle命令

Gradle的生命周期

Gradle项目的生命周期分为三大阶段:

  1. Initialization 初始化

    1. 执行初始化脚本(init.d/*.gradle

    2. 执行settings.gradle,主要包含当前项目声明以及当前项目子模块声明

    3. 生成项目工程树

  2. Configuration 配置

    1. 根据初始化阶段得到的项目工程树

    2. 依次调用每个模块的build.gradle脚本

    3. 调用顺序为先加载跟工程的,再加载所有的二级子工程的脚本,然后是三级子工程所有...

    4. 加载的build.gradle脚本最终会生成一个由task组成的有向无环数

  3. Execution 执行

    1. 根据有向无环数依次执行task,完成构建

settings.gradle

主要是在项目初始化阶段为项目工程树做准备:

  1. 位于项目根路径

  2. 名称必须为 settings.gradle

  3. 定义了当前gradle项目以及子项目的名称

  4. 每个项目只能有一个settings.gradle文件,他在gradle内部会生成一个org.gradle.api.initialization.Settins实例

  5. 是gradle的识别标志,没有该文件不会认为该项目是一个gradle项目

  6. 使用inclue('路径')引入项目模块

// 根项目名
rootProject.name='root'
// 子项目名
include 'subject01'
include 'subject02'
include 'subject03'
// 三级子项目
include 'subject01:subproject011'
include 'subject01:subproject012'
include 'subject01:subproject013'

// include 实际就是seetings实例的方法

在gradle中, : 可以试做 /,如果以:开头,代表是根目录开始。

build.gradle

  1. build.gradle是一个gradle构建脚本,支持java、groovy语法

  2. 每个project实例对应一个build.gradle脚本,文件中的所有方法调用都是调用的project对象的实例方法。

  3. RootProject也可以拥有一个build.gradle脚本文件,通常用来设置子project的一些公共信息,比如仓库、所有应用依赖的插件、所有应用的依赖项

下面是一个标准的 build.gradle

plugins {
    id 'java'
}

group 'org.example'
version '1.0-SNAPSHOT'

repositories {
    mavenCentral()
}

dependencies {
    testImplementation 'org.junit.jupiter:junit-jupiter-api:5.8.1'
    testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine:5.8.1'
}

test {
    useJUnitPlatform()
}

属性:项目坐标 group name version

自带属性:group,name,version 对应maven的GAV,用于表示项目的坐标。其中,group与version信息配置在build.gradle文件中,而name则是配置在settings.gradle文件中。

build.gradle:

group 'com.yangsx95'
version '1.0'

settings.gradle:

rootProject.name = 'microservice'
include 'subject01'

属性:自定义属性信息 ext

可以使用ext方法定义自定义属性,并引用:

ext.age = 18
ext {
    phone = 18898989986
    address = '北京'
}

ext信息不仅可以放在build.gradle中,还可以放在任务中:

task extCustomProperty {
    ext {
        desc = 'hello'
    }
    doLast {
        println "${desc}"
    }
}

方法:repository

repositories {
    maven { url "$rootDir/lib/release" } // 本地lib目录
    maven { url 'file:///usr/local/repostory' } // 本地maven仓库,指定路径
    mavenLocal() // 本地maven仓库,settings.xml中配置的路径
    maven { name "Alibaba" ; url "https://maven.aliyun.com/repository/public" } // 阿里云maven
    mavenCentral() // maven中央仓库
    google() // google仓库
}

定义仓库,gradle在下载依赖的时候,会从上到下依次从每个仓库中寻找需要的依赖。如果找到将会停止向下搜索,如果找不到则继续向下查找。

方法:dependencies

在gradle中,依赖有三种方式:

  1. 本地依赖,依赖本地的某个jar,可以通过文件集合、文件树的方式指定

  2. 项目依赖,依赖某个定义在settings.gradle的project

  3. 直接依赖,依赖类型 依赖组名 依赖名称 依赖版本号

dependencies {
    // ****** 本地依赖 *********
    // 文件集合
    implementation files('lib/mysql.jar', 'lib/log4j.jar')
    // 文件树
    implementation fileTree('dir': 'lib', includes: ['*.jar'], excludes: ['mysql.jar', 'log4j.jar'])

    // ****** 项目依赖 *********
    implementation project(":subproject01")
    
    // ****** 直接依赖 *********
    // 默认方式
    implementation group:'redis.clients', name: 'jedis', version: '2.9.0'
    // 使用命名参数简化
    implementation 'org.springframework.data:spring-data-redis:2.0.0.RELEASE'
}

依赖的下载

当执行build命令时,gradle就会去配置的依赖仓库中下载对应的jar,并应用到项目中。

依赖的类型

相当于maven的scope:

依赖类型描述示例

compileOnly

由java插件提供,适用于编译器需要,但是打包不需要的情况

servlet-api容器已经提供

runtimeOnly

由java插件提供,只在运行期有效,编译器不需要

mysql的驱动包,编译期间不需要知道驱动包的细节,但是运行时必须有

implementation

由java插件提供,针对源码目录,在编译运行都有效

比如commons-lang、spring等

testCompileOnly

由java插件提供,用于编译测试的依赖项

testRuntimeOnly

由java插件提供,用于运行时需要的依赖项,编译不需要

testImplementation

由java插件提供,测试编译、运行期间都需要

api

由java-library插件提供,与implementation基本一致,但是提供了依赖传递的效果

compileOnlyApi

由java-library插件提供,在编译器有效,运行期无效,其他与api一致

apiimplementation的区别,假设有四个模块:

  1. A implementation B, B implementation C, A模块编译期间无法使用C中的类

  2. A implementation B, B api C,则A可以在编译期间使用C种的类

  3. A implementation B, B implementation C, C api D,则B编译期间可以使用A种的类,但是A不能使用B中的类

  4. A implementation B, B api C, C api D, 这样可以使用D

总的来说,api标记了这个依赖项是否可以被需要依赖当前项目的人使用;而implementation则代表当前依赖项仅供当前项目使用,不能被其他需要依赖该项目的项目使用。因为api的模块需要暴露给别的模块使用,将会影响编译速度。在开发过程中,优先选择implementation,如果涉及到多模块的依赖,再考虑使用api。注意当项目中拥有大量的api依赖项会显著增加构建时间。

高版本gradle已经废弃了 api,使用implementation即可

依赖冲突的解决

在编译期间,如果系统中出现同一依赖的不同版本,构建系统应该选择什么版本进行构建的问题:

  1. 项目依赖A模块,A模块依赖了log4j1.0

  2. 项目还依赖了B模块,B模块依赖了log4j2.0

  3. 编译期间不知道该使用log4j1.0还是log4j2.0

默认情况下,Gradle会使用最新的jar,比如上述案例就会使用log4j2.0的jar,自动剔除1.0的jar。

如果不想遵循默认的规则,可以通过exclude手动排除某个冲突的jar:

implementation('org.xxx.xxx:1.0') {
    // 排除组
    exclude group: 'org.apache'
    // 排除模块
    exclude module: 'log4j'
    // 排除某个组的具体的依赖
    exclude group: 'org.apache',module: 'log4j'
}

或者禁用引用包的依赖传递,这样打包时也可以提出某个依赖(不建议使用):

implementation('org.xxx.xxx:1.0') {
    transitive(false)
}

或者强制使用某个版本,让项目目中所有涉及当前依赖的模块都是用这个版本:

// 使用!!强制使用版本
implementation 'org.apache:log4j:1.0!!'

使用依赖最新版本

// 下面两种方式是相同的
implementation 'org.apache:log4j:+'
implementation 'org.apache:log4j:lastest.intergration'

不建议使用。

方法:allprojects、subprojects、project

主要解决问题:如果在某个build.gradle中定义一些配置以及依赖,那么这些配置依赖只会对当前项目有效,他的子项目不会生效。

allprojects 设置当前工程以及当前工程的所有子工程一起设置,通常放在rootproject/build.gradle中:

allprojects {

}

而subprojects是对当前工程下的所有子工程设置,当前工程下不设置:

subprojects {

}

subprojects和allprojects可以为项目设置公用的插件、依赖、属性,此外,还可以使用project方法,对某个子工程进行一些独立的设置:

project('subproject1') {

}

注意

  1. subproject1 名字定义在了settings.gralde

  2. 在allprojects、subprojects、project不支持语法 plugins {}应用插件,需要使用apply plugin: 'xx' 替换

方法:sourceSets

设置项目源集,比如java的默认源码目录src/main/java,以及构建结果目录。

方法:apply、plugins

前两者是旧的插件依赖方式,plugins则是新的插件依赖方式。

plugins {
    id 'java'
}

方法:buildScript

buildscript里是gradle脚本执行所需依赖,分别是对应的maven库和插件

  1. buildScript必须在build.gradle文件的最顶端,因为需要为执行脚本做准备

  2. 对于多项目构建,项目的 buildScript 方法声明的依赖关系可用于其所有子项目的构建脚本,类似allprojects、subprojects

  3. 这里定义的依赖可能是普通依赖,也可能是插件依赖

buildscript {
    repositories {
        jcenter()
        maven {
            url 'https://maven.google.com/'
            name 'Google'
        }
        google()
    }
    dependencies {
        classpath 'com.android.tools.build:gradle:3.3.1'
    }
}

gradle.properties

Task

Project实质上是Task对象的集合。一个Task表示一个逻辑较为独立的执行过程,比如编译、文件拷贝、打包等,甚至是一个简单的系统命令。一个Task可以读取和设置Project的Property以完成特定的操作。

定义Task

build.gradle 中定义一个简单的Task:

plugins {
    id 'java'
}

group 'org.example'
version '1.0-SNAPSHOT'

repositories {
    mavenCentral()
}

dependencies {
    testImplementation 'org.junit.jupiter:junit-jupiter-api:5.8.1'
    testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine:5.8.1'
}

test {
    useJUnitPlatform()
}

// task(name, Closure)
task task1 {
    // 任务配置,在配置阶段执行
    println '这是一个简单的任务'

    // 配置任务的行为,在任务执行阶段执行
    doFirst {
        println 'task1 doFirst'
    }
    doLast {
        println 'task1 doLast'
    }
}

// 可以将任务的行为定义到外部
task1.doFirst {
    println 'task1 doFirst'
}

// 任务除了doFist、doLast这两个行为,还可以使用task方法的另一个重载,传入自身行为
def taskMap = new HashMap()
taskMap.put("one", { println "one"})
taskMap.put("two", { println "two"})
taskMap.put("three", { println "three"})
task(taskMap, "task2") {
    println '这是一个简单的任务2'

    doFirst {
        println 'task1 doFirst2'
    }
    doLast {
        println 'task1 doLast2'
    }
}

// 再或者使用 create() 方法
tasks.create("E") {
    println "taskE"
}

// 也可以使用project.tasks.register()方法注册一个task,作用是相同的 
// 注意register 是延迟创建,只有使用的时候才开始创建
tasks.register("F") {
    println "taskF"
}

执行task:

# -i 表示日志级别为info
# gradle -i task名称
gradle -i task1
gradle -i task2

Task的执行原理

task中的所有行为是一个action实例,这些实例会放入到一个列表中,列表的最前面是一个或者多个doFirstAction,最后面则是一个或者多个doLastAction。先添加的将会放在列表的前面。

指定Task的属性

配置项描述默认值

type

指定父task,基于另一个task创建新的task

DefaultTask

overwrite

是否替换存在的Task,这个和type配合使用

false

dependsOn

配置任务的依赖关系

[]

action

添加到任务中的Action或者一个闭包

null

description

任务描述

null

group

任务分组,比如testbuild

null

示例:

// 方式一,内部指定属性
task("taskH") {
    group("yangsx95")
    description("demo task h")
}

// 方式二,外部指定属性
task "y" {}
y.group = "yansx"

// 方式三,构造方法
task(group: "yangsx", description: "task G", "G")

type

默认的task继承自DefaultTask类型,如果要完成某些具体的操作,完全需要我们自己去编写gradle脚本,这样肯定有些麻烦,所以提供了type属性去继承某个task,复用他的一些逻辑。官方为我们提供了一些默认的TaskType使用:

常见的任务类型作用

Delete

删除文件或目录

Copy

将文件复制到目标目录中,还可以在复制时重命名和筛选文件

CreateStartScripts

创建启动脚本

Exec

执行命令进程

GenerateMavenPom

生成Maven Pom文件

GradleBuild

执行Gradle构建

Jar

组装Jar归档文件

JavaCompiler

编译Java源码

Javadoc

为Java代码生成HTML API

PublishToMavenRepository

推送到远程maven仓库

Tar

组装tar归档文件

Test

执行Junint或者TestNG测试

Upload

将Configuration的构建上传到一组存储库

War

组装war归档文件

Zip

组装Zip归档文件

示例(删除构建目录):

tasks.register("myClean", Delete) {
    delete buildDir
}

或者使用类继承的方式:

class CustomTask exteds DefaultTask {
    @TaskAction
    def doSelf() {
        // ...
    }
}

dependsOn

build.gradle可以定义多个task,多个task可能存存在依赖关系:

task A {
    doLast {
        println 'TaskA'
    }
}

task B {
    doLast {
        println 'TaskB'
    }
}

task C {
    // task C 依赖 A 和 B
    // 被依赖的任务会先执行
    dependsOn([A, B])
    // 也可以依赖工程下某个项目的某个任务
    // dependsOn(":subject01:A")
    doLast {
        println 'TaskC'
    }
}

任务的执行顺序

有三种方式控制任务的执行顺序:

  1. dependsOn 强依赖方式(不推荐)

  2. 通过 Task 输入输出(不推荐)

  3. 通过API指定执行顺序

// 任务的执行顺序, bTask 依赖 aTask
task aTask {
    doFirst {
        println "aTask"
    }
    group("my")
}
task bTask {
    doFirst{
        println "bTask"
    }
    group("my")
    dependsOn("aTask")
}

动态分配任务

// 动态分配任务
// 右侧task会新增一个my组里面多出四个task
4.times { counter -> 
    tasks.register("task$counter") {
        group('my')
        doLast {
            println "I'm task number $counter"
        }
    }
}

任务关闭与开启

// 设置一个关闭状态的任务,或者动态关闭某个任务
task 'disableMe' {
    doLast {
        println 'This is not executing'
    }
    group('my')
    enabled(false) // 默认设置任务处于关闭状态
}
// 重新开启任务
tasks.named('disableMe') {
    enabled(true)
}

任务的超时

可以为任务设置超时时间,如果大于超时时间,则会抛出一个异常,并且中断后面的任务执行:

// 任务的超时
task 'timeoutTask' {
    doLast {
        Thread.sleep(1000)
        println '超时任务执行'
    }
    group('my')
    // 设置超时时间属性为500毫秒
    timeout = Duration.ofMillis(500)
}

任务的定位和查找

// 直接通过project属性获取
println "project 属性:${project.tasks.searchTask.name}"

// 通过collection获取
println "tasks collections:${tasks['searchTask'].name}"

// 使用findByName通过任务名称在当前模块中查找指定的任务
tasks.findByName('searchTask').doFirst({ println 'searchTask --- first (byName)' })

// 使用findByPath通过路径查找指定的任务
tasks.findByPath(':notes-gradle:searchTask').doFirst({ println 'searchTask --- first (byPath)' })

任务的onlyIf断言

只有满足目标条件的时候,任务才会执行,否则将会跳过。

// 任务的onlyIf断言
// 只有满足目标条件的时候,任务才会执行,否则将会跳过
task onlyIfTask {
    doLast {
        println 'onlyIfTask'
    }
    onlyIf {
        project.hasProperty("compileVersion")
    }
    group 'my'
}

输出结果:

> Task :notes-gradle:onlyIfTask SKIPPED

操作文件

// project对象提供了file方法,可以用来读取或者创建文件或者目录
File configFile = file('config.xml')
configFile.createNewFile()
// 另外,还提供了files方法,一次创建多个文件
def fileList = files('config1.xml', 'config2.xml', 'config3.xml')
fileList.forEach(f -> {
    println f.name
})
// 文件集合可以做加减元素操作
def newFileList = fileList - files('config4.xml')
newFileList.forEach(f -> {
    println "new: ${f.name}"
})
// 删除文件()
configFile.delete()

// 树递归获取所有文件,并且只保留java文件
fileTree('src/main').include('**/*.java').forEach(item -> {
    print item.name
})
// 闭包的方式
fileTree('src/main') {
    exclude '**/*.xml'
}

拷贝文件,常产用于生成构建内容。下面是通过CopyTask的方式:

// 文件拷贝
task copyTask(type: Copy) {
    // 拷贝谁
    from 'src/main/webapp'
    from 'src/main/resource/static/index.html'
    from zipTree('xx.zip') // 解压压缩包拷贝
    // 拷贝时修改文件名
    rename { String filename -> 
        filename.replace('-dev', '-test')
    }
    // 拷贝到xx目录
    into 'build/exportWar'
}

project也提供了相应的copy方法:

copy {
    from file('src/main/resources/*')
    into this.buildDir.absolutePath
}

文件归档:

task myZip(type: Zip) {
    from 'src/main'
    into 'build' // 保存到build目录中
    archiveFileName = 'myGame' // 打包文件名
}

默认任务

默认情况下,如果要执行某个任务,需要通过gradle -q taskName命令指定任务名称,然后才可以执行任务。如果想通过gradle直接执行某些任务,需要将任务设置为默认的任务:

// 默认任务
task 'defaultTask1' {
    doLast {
        println 'defaultTask1'
    }
    group 'my'
}
task 'defaultTask2' {
    doLast {
        println 'defaultTask2'
    }
    group 'my'
}
defaultTasks 'defaultTask1', 'defaultTask2'

运行gradle命令,将会显示:

> Task :notes-gradle:defaultTask1
defaultTask1

> Task :notes-gradle:defaultTask2
defaultTask2

Plugin

在项目中引用插件,可以:

  1. 添加插件定义好的task到项目中,帮助我们完成编译、测试、打包

  2. 添加一些新的依赖类型到项目中

  3. 向项目中扩展一些新的属性以及方法,比如加入插件之后,可以设置jdk的版本信息

  4. 插件可以对项目进行一些约定俗称的配置

Gradle插件分类:

  1. 脚本插件

  2. 二进制插件(对象插件)

    1. 内部插件

    2. 第三方插件

    3. 自定义插件

脚本插件

脚本插件是在项目中定义.gradle结尾的gradle脚本文件,然后引入到build.gradle中,比如下面定义了一个version.gradle的脚本,记录了当前java的版本信息:

ext {
    company = "哈利"
    cfgs = [
            compileSdkVersion: JavaVersion.VERSION_1_8
    ]
    spring = [
            version: '5.0.0'
    ]
}

build.gradle引如这个脚本,并创建一个Task使用脚本中生命的变量:

apply from: 'version.gradle'
print company // 哈利

对象插件(二进制插件)

所谓对象插件就是实现 org.gradle.api.Plugin 接口的插件,每一个插件都有且必须有一个 plugin id。可以通过apply使用插件:

// 使用内部插件java
apply plugin: 'java'

内部插件

内部也是核心插件,可以在 https://docs.gradle.org/current/userguide/plugin_reference.html查看所有的核心插件。

使用核心插件:

plugins {
    id 'java'
}

或者使用apply:

// map参数
apply(plugin:'java')
// 等同于
apply plugin:'java'
// 等同于
apply plugin:org.gradle.api.plugins.JavaPlugin
// 等同于
apply plugin:JavaPlugin

// 闭包参数
apply {
    plugin 'java'
}

第三方插件

不是gradle自带的,而是由其他第三方提供的插件,一般需要配置对应的仓库和类路径,否则找不到插件:

buildscript {
    
    ext {
        springBootVersion = '2.3.3.RELEASE'
    }
    
    // 引入仓库
    repositories {
        mavenLocal()
        mavenCentral()
    }
    
    // 引入插件依赖
    dependencies {
        classpath("org.springframework.boot:spring-boot-gradle-plugin:${springBootVersion}")
    }
    
}

// 应用插件
apply plugin: "org.springframework.boot"

如果插件已经被托管到 https://plugins.gradle.org 中,可以使用如下方式直接引入插件:

plugins {
    id 'org.springframework.boot' version '2.4.1'
}

自定义插件

通过实现Plugin<Project>接口创建一个project的插件,一个插件中可能包含多个task:

// 接口方式定义
class GreetingPlugin implements Plugin<Project> {
    void apply(Project project) {
        project.task('hello') {
            doLast {
                println 'Hello from the GreetingPlugin'
            }
        }
    }
}

// Apply the plugin
apply plugin: GreetingPlugin

上述方式只支持在一个模块中使用插件,如果想要多个模块之间共享插件,可以使用buildSrc的方式:

  1. buildSrc是Gradle的默认插件目录,编译插件时会自动识别这个目录,将其编译为插件。

  2. 先在根项目目录建立一个名称为buildSrc的gradle模块,并且不在settings.gradle中include这个模块,只保留build.gradle以及src/main

  3. 修改build.gradle

    plugins {
         id 'groovy'
         id 'maven-publish'
     }
    
     repositories {
         google()
         mavenCentral()
     }
    
     dependencies {
         implementation gradleApi()
         implementation localGroovy()
     }

如果多个项目之间需要使用同一个插件,我们将上述做好的插件单独抽成一个插件项目并将依赖包上传到maven私服中即可。如果要使用仓库,项目只需要依赖这个插件依赖,并apply即可:

plugins {
    id 'java-gradle-plugin'                           
    id 'maven-publish'                                
}

// 发布到本地
publishing {
    repositories {
        maven {
            name = 'localPluginRepository'
            url = '../local-plugin-repository'
        }
    }
}

使用 maven-publish 插件提供的task发布即可。

发布插件的官方文档:https://docs.gradle.org/current/userguide/publishing_gradle_plugins.html

三方插件关注点

  1. 如何引入插件

  2. 插件所包含的主要task

  3. 插件约定的工程结构(约定优于配置)

  4. 插件提供的依赖管理以及依赖的类型、

  5. 插件提供的额外的属性,可以再build.gradle中使用

Java插件示例,参考官方文档: https://docs.gradle.org/current/userguide/java_plugin.html#java_plugin

最后更新于