1、Gradle基础
1.1、Ant/Maven/Gradle对比
无论那种项目构建工具,都有自身的优势和劣势,所以选择一款最适合项目的就是最好的!
1.2、Gradle项目目录结构
Gradle项目默认目录结构和Maven项目的目录结构一致,都是基于约定大于配置【Convention Over Configuratiion】
1.3、Gradle中的常用命令
注意:gradle的指令要在含有build.gradle的目录执行。
1.4、修改maven下载源
Gradle自带的Maven源地址是国外的,该Maven源在国内的访问速度是很慢的,除非使用了特别的手段。一般情况下,我们建议使用国内的第三方开发的Maven源或企业内部自建Maven源。
- 认识init.d文件夹:
我们可以在gradle的init目录下创建以.gradle结尾的文件,.gradle文件可以实现在build开始之前执行,所以你可以在这个文件配置一些你想预先加载的操作。 - 在init.d文件夹创建init.gradle文件:
拓展1:启用init.gradle文件的方法有:
拓展2:仓库地址说明:
1.5、Wrapper包装器
Gradle Wrapper实际上就是对Gradle的一层包装,用于解决实际开发中可能会遇到的不同的项目需要不同版本的Gradle问题。例如:把自己的代码共享给其他人使用,可能出现如下情况:
1、对方的服务器没有安装gradle
2、对方的服务器安装过gradle,但是版本太旧了
这时候,我们就可以考虑使用Gradle Wrapper了。这也是官方建议使用Gradle Wrapper的原因。实际上有了Gradle Wrapper之后,我们本地是可以不配置Gradle的,下载Gradle项目后,使用gradle项目自带的wrapper操作也是可以的。
2、Geoovy简介
在某种程度上,Grooovy可以被视为Java的一种脚本化改良版,Groovy也是运行在JVM上,它可以很好地与Java代码以及相关的库进行交互操作。它是一种成熟的面向对象编程语言,既可以面向对象编程,又可以用做纯粹的脚本语言。大多数有效的Java代码也可以转换为有效的Groovy代码,Groovy和Java语言的主要区别是:完成同样的任务所需的Groovy代码比Java代码更少。其特点为:
- 功能强大,例如提供了动态类型转换、闭包和元编程(metaprogramming)支持
- 支持函数式编程,不需要main函数
- 默认导入常用的包
- 类不支持default作用域,且默认作用域为oublic
- Groovy中基本类型也是对象,可以直接调用对象的方法
- 支持DSL(Domain Specific Languages 领域特定语言)和其它简洁的语法,让代码变得易于阅读和维护
- Groovy是基于Java语言的,所以完全兼容Java语法,所以对于Java程序员学习成本较低。
2.1、Groovy基本语法
1、Groovy是基于Java语言的,所以完全兼容Java语法,可以作为面向对象编程语言【定义类】,也可以作为脚本型语言【文件定义中不出现类】。
2、在一个groovy文件中可以混合类的定义和脚本定义,此时不要定义一个和文件同名的类。
3、groovy中使用def定义变量、方法,不建议使用具体的数据类型。
4、groovy中的注释:单行注释用//,多行注释用:/**/。
5、groovy中语句末尾的分号是可以省略的,以换行符作为结束。
6、默认类、方法、字段都是public修饰的。
7、支持顺序结构、分支结构、循环结构语句。
8、支持各种运算符:算术、关系、位、赋值、范围运算符。
9、基本类型也是对象,可以直接调用对象的方法。
10、groovy中的字符串有单引号:作为字符串常量使用,没有运算能力;双引号:可以引用变量${},有运算能力;三个引号:模版字符串,支持换行。
11、数据类型:变量,属性,方法,闭包的参数以及方法的返回值的类型都是可有可无的,都是在给变量赋值的时候才决定它的类型。
类型转换:当需要时,类型之间会自动发生类型转换:字符串(String)、基本类型(如int)和类型的包装类(如Integer);
类说明:如果在一个groovy文件中没有任何类定义,它将被当做script来处理,也就意味着这个文件被透明的转换为一个Script类型的类,这个自动转换的类将使用原始的groovy文件名作为类的名字。groovy文件的内容被打包进run方法,另外在新产生的类中被加入一个main方法以进行外部执行该脚本。
3、Gradle进阶
3.1、Gradle项目的生命周期
Gradle项目的生命周期分为三大阶段:Initialization->Configuration->Execution.每个阶段都有自己的职责,具体如下图所示:
**Initialization阶段:**主要是初始化构建,它又分为两个子过程,一个是执行Init Script,另一个是执行Setting Script。
**Configuration阶段:**这个阶段开始加载项目中所有模块的Build Script。所谓“加载”就是执行build.gradle中的语句,根据脚本代码创建对应的task,最终根据所有task生产由Task组成的有响无环图(Directed Acyclic Graphs),如下:
从而构成如下有向无环树:
Execution阶段:这个阶段会根据上个阶段构建好的有向无环图,按着顺序执行Task【Action动作】。
3.2、settings文件
首先对settings文件做以下几点说明:
1、作用:主要是在项目初始化阶段 确定一下引入哪些工程需要加入到项目构件中,为构建项目工程树做准备。
2、工程树:gradle中有工程树的概念,类似与maven中的project与module。
3、内容:里面主要定义了当前gradle项目及子project的项目名称。
4、位置:必须放在根工程目录下。
5、名字:为settings.gradle文件,不能发生变化。
6、对应实例:与org.gradle.api.initialization.Settings实例是一一对应的关系。每个项目只有一个settings文件。
7、关注:作为开发者我们只需要关注该文件中的includeing方法即可。使用相对路径【:】引入子工程。
8、一个子工程只有在setting文件中配置了才会被gradle识别,这样在构建的时候才会被把包含进去。案例如下所示:
项目名称中":“代表项目的分隔符,类似路径中的”/“,如果”:"开头则表示相对于rootProject。然后Gradle会为每个带有build.gradle脚本文件的工程构建一个与之对应的Project对象。
3.3、Task
项目实质上是Task对象的集合。一个Task表示一个逻辑上较为独立的执行过程,比如编译Java源代码,拷贝文件,打包Jar文件,甚至可以是执行一个系统命令。另外,一个Task可以读取和设置Project的Property以完成特定的操作。
3.3.1、任务入门
在文件所在的目录执行命令:gradle A。
提示1:task的配置是在配置阶段完成的。
提示2:task的doFirst、doLast方法是执行阶段完成的,并且doFirst在doLast执行之前执行。
提示3:区分任务的配置阶段和任务的行为,任务的配置是在配置阶段执行,任务的行为是在任务执行阶段执行。
3.3.2、任务的行为
案例如下:doFirst、doLast两个方法可以在任务内部定义,也可以在任务外部定义
测试:gradle a,输出如下所示:
3.3.3、任务的依赖方式
Task只见的依赖关系可以在以下几个部分设置:
方式一:参数方式依赖
方式二:内部依赖
方式三:外部依赖
当然:task也支持跨项目依赖。
拓展1:当一个Task依赖多个Task的时候,被依赖的Task之间如果没有依赖关系,那么它们的执行顺序是随机的,并无影响。
拓展2:重复依赖的任务只会执行一次,比如:A——>B、C;B——>C;任务A依赖任务B和任务C、任务B依赖C任务。执行任务A的时候,显然任务C被重复依赖了,C只会执行一次。
3.3.4、任务执行
#常见的任务
#构建项目,编译、测试、打包等操作
gradle build
#运行一个服务,需要application插件支持,并且指定了主启动类才能运行
gradle run
#清理当前项目的build目录
gradle clean
#初始化gradle项目
gradle init
#生成wrapper文件件的
gradle wrapper#项目报告相关任务
#列出所选项目及子项目列表,以层次结构的形式显示
gradle projects
#列出所选项目【当前projects,不包含父、子】的已分配给任务组的哪些任务
gradle tasks
#列出所选项目的所有任务
gradle tasks -all
#列出所选项目中指定分组中的任务
gradle tasks -group="build setup"
#显示某个任务的详细信息
gradle help -task someTask
#查看整个项目的依赖信息,以依赖树的方式显示
gradle dependencies
#列出所选项目的属性列表
gradle properties#调试相关选项
#查看帮助信息
-h,-help
#打印Gradle、Groovy、Ant、JVM和操作系统版本信息
-v,-version
#打印出所有异常的完整堆栈跟踪信息
-S,-full,-stacktrace
#打印出用户异常的堆栈跟踪信息
-s,-stacktrace
#调试Gradle守护进程
-Dorg.gradle.daemon.debug=true;
#指定启用调试时要侦听的端口号,默认值为5005
-Dorg.gradle.debug.port=(port number)#性能选项,一般在gradle.properties中指定这些选项中的许多选项,因此不需要命令行标志
#尝试重用先前版本的输出,默认关闭(off)
--build-cache,--no-build-cache;
#设置Gradle可以使用的worker数。默认值是处理器数
--max-workers
#并行执行项目,默认设置为关闭(off)
-parallel,-no-parallel#守护进程选项
#使用Gradle守护进程运行构建,默认是on
-daemon,-no-daemon
#在前台进程中启动Gradle守护进程
-foreground
-Dorg.gradle.daemon.idletimeout=(number of milliseconds)
#将在这个空闲时间的毫秒数之后停止自己。默认值为10800000(3小时)
Gradle Daemon#日志选项
-Drog.gradle.logging.level=(quiet,warn,lifecycle,info,debug);
#通过Gradle属性设置日志记录级别
#只能记录错误信息
-q,-quiet
#设置日志级别为warn
-w,-warn
#将日志级别设置为info
-i,-info
#登录调试模式(包括正常的堆栈跟踪)
-d,-debug#其它
#等价于:-exclude-task,常见gradle -x test clean build
-X:-x
#强制执行任务,忽略up-to date,常见gradle build -return-tasks
-return-tasks
#忽略前面失败的任务,继续执行,而不是在遇到第一个失败时立即停止执行,每个遇到的故障都将在构建结束时报告,常见:gradle build continue
-contiune
#将maven项目转换为gradle项目(根目录执行)
gradle init -type pom
#执行自定义任务
gradle[`taskName]
扩展1:gradle任务名时缩写:任务名称支持驼峰式命名的任务名缩写,如:connectTask简写为:cT,任务执行任务gradle cT。
拓展2:gradle默认各指令之间相互的依赖关系:
3.3.5、任务定义方式
任务定义方式,总体分为两大类:一种是通过Project中的task()方法,另一种是通过tasks对象的creat或者register方法。
task('A',{// 任务名称,闭包都作为参数println "taskA..."
})task('B){// 闭包作为最后一个参数可以直接从括号中拿出来println "taskB..."
}task C{// groovy语法支持省略方法括号println "taskC..."
}def map=new HashMap<String,Object>();
map.put("action",{println "taskD"}) //action属性可以设置为闭包
task(map,"D");
task.create('E'){// 使用tasks的creat方法println "taskE..."
}tasks.register('f'){println "taskF..."
}
3.3.6、任务的类型
常见的task都是DefaultTask类型的,如果要完成某些具体的操作完全需要我们自己去编写gradle脚本,势必有些麻烦,那有没有一些现成的任务类型可以使用呢?有的,Gradle官网给出了一些现成的任务类型帮助我们快速完成想要的任务,我们只需要在创建任务的时候,指定当前任务的类型即可,然后即可使用这些类型中的属性和API方法了。
常见的任务类型 | 该任务的作用 |
---|---|
Delete | 删除文件或目录 |
Copy | 将文件复制到目标目录中。此任务还可以在复制时重命名和筛选文件 |
CreateStartScripts | 创建启动脚本 |
Exec | 执行命令进程 |
GenerateMavenPom | 生成Maven模块描(POM)文件 |
GradleBuild | 执行Gradle构件 |
Jar | 组装JAR归档文件 |
JavaCompile | 编译Java源文件 |
Javadoc | 为Java类生成HTML API文档 |
PublishToMavenRepository | 将MavenPublication发布到mavenartifactrepostal |
Tar | 组装JAR存档文件 |
Test | 执行Junit(3.8x、4.x或5.x)或TestNG测试 |
Upload | 将Configuration的构件上传到一组存储库 |
War | 组装WAR档案 |
Zip | 组装ZIP归档文件。默认是压缩ZIP的内容 |
拓展:自定义Task类型
3.3.7、任务的执行顺序
在Gradle中有三种方式可以指定Task执行顺序:
1、dependsOn强依赖方式
2、通过Task输入输出
3、通过API指定执行顺序
3.3.8、动态分配任务
gradle的强大功能不仅仅用于定义任务的功能。列如,可以使用它在循环中注册同一类型的多个任务:
4.times{counter->tasks.register("task$counter"){doLast{println "I am task bumer $counter"}}
}
一旦注册了任务,就可以通过API访问它们。列如,您可以使用它在运行时动态地向任务添加依赖项。Ant不允许这样的事情发生。
4.times{counter->tasks.register("task$counter"){doLast{println "I am task bumer $counter"}}
}
tasks.named('task0'){dependsOn('task2','task3')}
构建4个任务,但是任务0必须依赖于任务2和任务3,那么代表任务2和任务3需要在任务0之前优先加载。具体测试如下:
3.3.9、任务的关闭与开启
每个任务都有一个enabled默认标志true。将其设置为false阻止执行任何任务动作。禁用的任务将标记为“跳过”。
task disableMe{doLast{println 'This task is Executing...'}enable(true)// 直接设置任务开启,默认值为true
}
// disableMe.enable=false 设置关闭任务
3.3.10、任务的超时
每个任务都有一个timeout可用于限制其执行时间的属性。当任务达到超时,其任务执行线程被中断,该任务将被被标记为失败,终结器任务任将运行。如果-continue使用,其任务可以在此之后继续运行。不影响中断的任务无法超时。Gradle的所有内置任务均会及时响应超时。
task a(){doLast{Thread.sleep(1000)println "当前任务a执行了"}timeout=Duration.ofMillis(500)
}task b(){doLast{println"当前任务b执行了"}
}
在控制台使用:gradle a b测试会发现执行a的时候,由于a执行超时,抛出异常,所以没有继续往下执行【b也没执行】。
然后在控制台使用:gradle a b -continue,测试会发现a虽然失败,但是b还是执行了。
3.3.11、任务的查找
常用的任务查找方法有:
task test{doLast{println "精诚所至金石为开!" }
}
// 根据任务名查找
tasks.findByName("test").doFirst({println "遇事不决便问春风"})
tasks.getByName("test").doFirst({println "春风不语"})
// 根据任务路径查找【相对路径】
tasks.findByPath("test").doFirst({println "春风、阳光、空气"})
tasks.getByPath("test").doFirst({println "都是幸福哦"})
3.3.12、任务的规则
当我们执行、依赖一个不存在的任务时,Gradle会执行失败,报错误信息。那我们能否对其进行改进,当执行一个不存在的任务时,不是报错而是打印提示信息呢?
task hello{doLast{println 'hello everyone' }
}tasks.addRule('对该规则的一个描述,便于调试、查看等'){String taskName->task(taskName){doLast{println '该${taskName}任务不存在,请查证后再执行'}}
}
测试:使用gradle abc hello
进行测试,此时当abc任务不存在时,也不会报异常【不中断执行】而是提示自定义的规则信息,继续执行hello任务。此外,它还可以根据不同的规则动态创建需要的任务等情况。
3.3.13、任务的onlyIf断言
断言就是一个条件表达式。task有一个onlyIf方法。它接受一个闭包作为参数,如果该闭包返回true则该任务执行,否则跳过。这有很多用途,比如控制程序那些情况下打什么包。什么情况下执行单元测试,什么情况下执行单元测试的时候不执行网络测试等。具体案列如下所示:
task hello{doLast{println 'hello worild!' }
}hello.onlyIf{!project.hasProperty('fancy')}
测试:通过-P为Project添加fancy属性
gradle hello -Pfancy
3.3.14、默认任务
Gradle允许您定义一个或多个在没有指定其他任务时执行的默认任务。
代码如下:
defaultTasks 'myClean','myRun'
tasks.register('myClean'){doLast{println 'Default Cleaning!' }
}
tasks.register('myRun'){doLast{println 'Default Running!' }
}
tasks.register('other'){doLast{println 'I am not a default task!' }
}
测试:gradle -q
4、Gradle中的文件操作
几种常见的文件操作方式:
- 本地文件
- 文件集合
- 文件树
- 文件拷贝
- 归档文件
4.1、本地文件
使用Project.file(java.lang.Object)方法,通过指定文件的相对路径或绝对路径来对文件的操作,其中相对路径为相对当前project[根project或者自project]的目录。其实使用Project.file(java.lang.Object)方法创建的File对象就是Java中的File对象,我们可以使用它就像在Java中一样。示例代码如下:
// 使用相对路径
File configFile=file('src/config.xml')
configFile.createNewFile();
// 使用绝对路径
configFile=file('D:\\conf.xml')
println(configFile.createNewFile())
// 使用一个文件对象
configFile=new File('src/config.xml')
println(configFile.exists())
4.2、文件集合
文件集合就是一组文件的列表,在Gradle中,文件集合用FileCollection接口表示。我们可以使用Project.files(java.lang.Object[])方法来获得集合对象,如下代码,创建一个FileCollection实例:
对于文件集合,我们可以遍历它;也可以把它转换成Java类型;同时还能使用+来添加一个结合,或使用-来删除集合。
4.3、文件树
文件树是有层级结构的文件集合,一个文件树它可以代表一个目录或者ZIP压缩包中的内容结构。文件树是从文件集合继承过来的,所以文件树具有文件集合的所有功能。我们可以使用Project.FileTree(java.utilMap)
方法来创建文件树对象,还可以使用过滤条件来包含或排除相关文件。实例底代码如下:
4.4、文件拷贝
我们可以使用Copy任务来拷贝文件,通过它可以过滤指定拷贝内容,还能对文件进行重命名操作等。Copy任务必须指定一组需要拷贝的文件和拷贝到的目录,这里使用CopySpec.form(java.lang.Object[])
方法指定源文件;使用CopySpec.into(java.lang.Object[])
方法指定目标目录。实例代码如下:
task copyTask(type:Copy){from 'src/main/resources'into 'build/config'
}
4.4、归档文件
通常一个项目会有很多的Jar包,我们希望把项目打包成一个WAR,ZIP或TAR包进行发布,这时我们就可以使用Zip,Tar,Jar,War和Ear任务来实现,不过它们的用法都一样,所以在这里只介绍Zip任务的示例。
apply plugin:'java'
version=1.0
task myZip(type:Zip){from 'src/main'into 'build' //保存到build目录中baseName='myGame'
}
println myZip.archiveName
执行命令gradle -q myZip,输出结果为:
5、Dependencies
5.1、依赖的方式
Gradle中的依赖分别为直接依赖、项目依赖、本地jar依赖。
案例如下:
dependencies{// 1、依赖当前项目下的某个模块[子工程]implementation project(':subject01')// 2、直接依赖本地的某个jar文件implementation files('libs/foo.jar','libs/bar.jar')// 3、配置某文件夹作为依赖项implementation fileTree(dir:'lib',include:['*.jar'])// 4、直接依赖implementation 'org.apache.logging.log4j:log4j:2.17.2''
}
5.2、依赖的下载
当执行build命令时,gradle就会去配置的依赖仓库中下载对应的jar,并应用到项目中。
5.3、依赖的类型
类似于Maven的scope标签,gradle也提供了依赖的类型,具体如下所示:
5.4、api与implementation区别
5.5、依赖冲突及解决方案
依赖冲突是指“在编译过程中,如果存在某个依赖的多个版本,构建系统应该选择哪个进行构建的问题”,如下所示:
A、B、C都是本地子项目module,log4j是远程依赖。
解决方案:
不允许传递依赖:
6、Gradle插件
6.1、使用插件的原因
简单的说,通过插件我们可以:
1.促进代码重用、减少功能类似代码编写、提升工作效率
2.促进项目更高程度的模块化、自动化、便捷化
3.可插拔式的扩展项目的功能
6.2、插件的作用
在项目构件工程中做很多事情,把插件应用到项目中,通常可以完成:
- 添加任务【task】到项目中,从而帮助完成测试、编译、打包等。
- 添加依赖配置到项目中。
- 向项目中拓展新的扩展属性、方法等。
- 对项目进行一些约定,如应用Java插件后,约定src/main/java目录是我们源代码存在的位置,编译时编译这个目录下的Java源代码文件。
6.3、插件的分类和使用
6.3.1、脚本插件
脚本插件的本质是一个脚本文件,使用脚本插件时通过apply form:
将脚本加载进来就可以了,后面的脚本文件可以是本地的也可以是网络上的脚本文件,下面定义一段脚本,我们在build.gradle文件中使用它,具体如下:
// version.gradle文件
ext{company='久其'cfgs=[compileSdkVersion:JavaVersion.VERSION__1_8]spring=[version:'5.0.0' ]
}
下面将在构件文件中使用这个脚本文件,具体如下:
//build.gradle文件
apply from:'version.gradle'
task taskVersion{doLast{println "公司名称为:${company},JDK版本是¥{cfgs.compileSdkVersion},版本号是${spring.version}"}
}
意义:脚本文件模块化的基础,可以按功能把我们的脚本进行拆分为一个个公用、职责分明的文件,然后在主脚本文件引用,比如:将很多共有的库版本号一起管理、应用构建版本一起管理等。
6.3.2、二进制插件【对象插件】
二进制插件【对象插件】就是实现了org.gradle.api.Plugin接口的插件,每个Java Gradle插件都有一个plugin id。
可以通过如下方式使用一个Java插件:
apply plugin:'java'// map具名参数方式
或者:
// 也可以使用闭包作为project.apply方法的一个参数
apply{plugin 'java'
}
通过上述代码就将Java插件应用到我们的项目中了,对于Gradle自带的核心插件抖音唯一的plugin id,其中java是java插件的plugin id,这个plugin id必须是唯一的,可以应用包名来保证plugin id的唯一性。这里的java对应的具体类型是org.gradle.api.plugin.JavaPlugin,所以可以使用如下方式使用Java插件:
//使用方式1:Map具名参数.全类名
apply plugin:org.gradle.api.plugins.JavaPlugin
//使用方式2:org.gradle.api.plugins默认导入
apply plugin:JavaPlugin
// 使用方式3:插件的id
apply plugin:'java'
第二种:对象插件之第三方插件
如果使用第三方发布的二进制插件,一般需要配置对应的仓库和类路径
// 使用传统的应用方式
buildscript{ext{springBootVersion="2.3.3.RELEASE"}repositories{mavenLocal()maven{url 'http://maven.aliyun.com/nexus/content/groups/publics'}}// 此处先引入插件dependencies{classpath("org.springframework,boot:spring-boot-gradle-plugin:${springBootVersion}")}}
//再应用插件
apply plugin:'org.springframework.boot'// 社区插件,需要先事先引入,不必写版本号
但是如果第三方插件已经被托管在https://plugins.gradle.org/
网站上,就可以不用再buildscript里配置classpath依赖了,直接使用新出的plugins DSL的方式引用,案列如下:
plugins{id'org.springframework.boot'version'2.4.1'
}
第二种:对象插件之用户自定义插件
7、build.gradle文件
- build.gradle是一个gradle的构建脚本文件,支持java、groovy等语言。
- 每一个project都会有一个build.gradle文件,该文件是项目构建的入口,可配置版本、插件、依赖库等信息。
- 每个build文件都有一个对应的Project实例,对build.gradle文件配置,本质就是设置Project实例的属性和方法。
- 由于每个project都会有一个build文件,那么Root Project也不例外,Root Project可以获取所有Child Project,所以在Root Project的build文件中我们可以对Child Project统一配置,比如应用的插件、依赖的maven中心仓库等。
build文件中常见的属性和方法如下所示:
7.1、常见属性代码
7.2、Repositories
7.3、Subprojects与Allprojects
7.4、用户自定义配置
Project和Task都允许用户添加额外的自定义属性,添加额外的属性,通过应用所属对象的ext属性即可实现。添加之后可以通过ext属性对自定义属性读取和设置,如果同时添加多个自定义属性,可以通过ext代码块:
// 自定义一个Project属性
ext.age=18
// 通过代码块同时自定义多个属性
ext{phoe=123456789address="美丽的草原"
}task extCustomProperty{//在task中自定义属性ext{desc="奥利给" }doLast{println"年龄是:${age}"println"电话是:${phone}"println"地址是:${address}"println"口号:${desc}"}
}
7.5、Buildscript
buildscript里是gradle脚本执行所需要依赖,分别是对应的maven库和插件。
案例如下:
需要注意的是:
- bulidscript{}必须在build.gradle文件的最前端。
- 对于多项目构建,项目的buildscript()方法声明的依赖关系可用于其所有子项目的构建脚本。
- 构建脚本依赖可能是Gradle插件。
案例如下:
8、poublishing项目发布
接下来,将我们写好的模块发布到公司的私服以供别人使用,如下图所示:
8.1、引入maven发布的插件
8.2、设置发布代码
// 带源码和javadoc的发布:需要‘java-library’插件支持,它是java的升级版,java插件的功能java-library都有```powershell
publishing{publications{myLibrary(MavenPublication){groupId='org.gradle.sample' //指定GAV坐标信息artifactId='library'version='1.1'from components.java //发布jar包//from components.web //引入war插件,发布jar包}}
}
repositories {// 本地仓库mavenLocal()// 发布到项目私服中maven {url "https://nvwa.x.com.cn/nexus/repository/maven-nvware-group/"// 认证信息:用户名和密码credentials {username nexusUsernamepassword nexusPassword}allowInsecureProtocol = true}
}
8.3、执行发布指令
9、生命周期中HOOK
生命周期中的这些狗子函数都是gradle自动回调完成的,利用这些钩子函数可以帮助我们实现一些我们想要的功能。