Gradle——基础

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自动回调完成的,利用这些钩子函数可以帮助我们实现一些我们想要的功能。
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/636388.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

各种Linux版本安装Docker

文章目录 一、Ubuntu 20.04.61. 网卡和DNS配置2. Docker安装 二、CentOS Linux 7.91. 网卡和DNS配置2. Docker安装 三、Alibaba Cloud Linux 31. DNS配置2. repo说明3. Docker安装 四、验证是否安装成功 一、Ubuntu 20.04.6 1. 网卡和DNS配置 /etc/netplan 找到 *.yaml 文件 …

第十一站:C++面向对象-多态

为什么要使用多态 当定义的子类继承父类并重写父类的方法后, 父类使用指针调用子类的同名方法,得到的却是父类同名方法的结果 #include <iostream> using namespace std; class Father { public:void play() {cout << "一起去KTV唱歌吧" << end…

主板电路学习; 华硕ASUS A43S笔记本安装win7X64(ventoy)

记录 老爷机 白色 华硕 A43S 笔记本 安装 win7X64 1. MBR样式常规安装win7X64Sp1 (华硕 A43S 安装 win7X64 ) 老爷机 白色 华硕 A43S 笔记本 安装 win7X64 &#xff08;常规安装&#xff09; 设置&#xff1a; 禁用UEFI 启用AHCI ventoy制作MBR&#xff08;非UEFI&#xff…

OpenAI的DALL·e2生成的AI图像有时会带有偏见或NSFW

专家警告说&#xff0c;OpenAI的图像生成模型DALLe2可能玩起来很有趣&#xff0c;但它生成的图片可能会带有刻板印象和偏见&#xff0c;甚至是生成NSFW图片&#xff0c;因此在现实世界中部署会有风险。 OpenAI公司承认“如果没有足够的防护措施&#xff0c;像DALLe2这样的模型…

【Linux 内核源码分析】堆内存管理

堆 堆是一种动态分配内存的数据结构&#xff0c;用于存储和管理动态分配的对象。它是一块连续的内存空间&#xff0c;用于存储程序运行时动态申请的内存。 堆可以被看作是一个由各个内存块组成的堆栈&#xff0c;其中每个内存块都有一个地址指针&#xff0c;指向下一个内存块…

Wpf 使用 Prism 实战开发Day13

配置 AutoMapper 关系映射 在上一节 ToDoController 控制器&#xff0c;或 IToDoService 服务接口中&#xff0c;方法的传参都是直接传的实体类。但在实际开发过程中&#xff0c;这样是不允许的。标准且规范的做法是&#xff0c;定义一个数据传输层&#xff0c;即Dto层。 一.在…

51单片机矩阵键盘

矩阵键盘 矩阵键盘是一种常用于电子设备中的输入设备&#xff0c;其原理是利用行和列的交叉点来识别按键输入。矩阵键盘通常由多个按键排列成行和列的形式组成&#xff0c;通过按下某个按键可以在对应的行和列交叉点上产生电路连接。 在矩阵键盘中&#xff0c;每个按键都被安排…

【Linux】常见指令解析下

目录 前言1. cp指令&#xff08;重要&#xff09;2. mv指令 &#xff08;重要&#xff09;3. cat指令4. more指令5. less指令 &#xff08;重要&#xff09;6. head指令7. tail指令8. 时间相关的指令8.1 data显示8.2 时间戳 9. cal指令10. find指令&#xff08;非常重要&#x…

每日一练【最大连续1的个数】

一、题目描述 给定一个二进制数组 nums 和一个整数 k&#xff0c;如果可以翻转最多 k 个 0 &#xff0c;则返回 数组中连续 1 的最大个数 。 二、题目解析 本题同样是利用滑动窗口的解法。 首先进入窗口&#xff0c;如果是1&#xff0c;就直接让right&#xff0c;但是如果是…

会话跟踪技术(cookiesession)

文章目录 1、什么是会话跟踪技术2、Cookie2.1、Cookie基本使用2.2、Cookie原理2.3、Cookie使用细节 3、Session3.1、Session基本使用3.2、Session原理3.3、Session使用细节 4、Cookie和Session的对比 1、什么是会话跟踪技术 会话 ​ 用户打开浏览器&#xff0c;访问web服务器的…

2024美赛数学建模思路 - 案例:感知机原理剖析及实现

文章目录 1 感知机的直观理解2 感知机的数学角度3 代码实现 4 建模资料 # 0 赛题思路 &#xff08;赛题出来以后第一时间在CSDN分享&#xff09; https://blog.csdn.net/dc_sinor?typeblog 1 感知机的直观理解 感知机应该属于机器学习算法中最简单的一种算法&#xff0c;其…

cs231n assignment1——SVM

整体思路 加载CIFAR-10数据集并展示部分数据数据图像归一化&#xff0c;减去均值&#xff08;也可以再除以方差&#xff09;svm_loss_naive和svm_loss_vectorized计算hinge损失&#xff0c;用拉格朗日法列hinge损失函数利用随机梯度下降法优化SVM在训练集和验证集计算准确率&a…

产品经理 | 原型设计必须遵循的视觉设计规范(1)— 设计原则

前言&#xff1a;Hello大家好&#xff0c;我是小哥谈。本系列原型设计规范教程&#xff0c;主要用于规范系统的原型界面设计&#xff0c;使之具有良好的设计风格&#xff0c;帮助塑造品牌形象。通过定义原型的字体、图标、布局、颜色等信息&#xff0c;提供多样化的交互设计方案…

无法找到mfc100.dll的解决方法分享,如何快速修复mfc100.dll文件

在日常使用电脑时&#xff0c;我们可能会碰到一些系统错误提示&#xff0c;比如“无法找到mfc100.dll”的信息。这种错误通常会阻碍代码的执行或某些应用程序的启动。为了帮助您解决这一问题&#xff0c;本文将深入探讨其成因&#xff0c;并提供几种不同的mfc100.dll解决方案。…

1360. 卒的遍历-深度优先搜索-DFS

代码&#xff1a; #include<bits/stdc.h> using namespace std; int n,m; int r[25][3]; int fx[3]{0,1,0}; int fy[3]{0,0,1}; int a; void print(int k){a;cout<<a<<":";for(int i1;i<k;i){cout<<r[i][1]<<","<<…

[C#]winform部署yolov8图像分类的openvino格式的模型

【官方框架地址】 https://github.com/ultralytics/ultralytics 【openvino介绍】 OpenVINO是一个针对Intel硬件优化的开源工具包&#xff0c;用于优化和部署深度学习模型。以下是OpenVINO部署模型的主要优点&#xff1a; 高性能&#xff1a;OpenVINO提供了一系列性能优化工…

Flask 3.x log全域配置(包含pytest)

最近使用到flask3.x&#xff0c;配置了全域的log&#xff0c;这边记录下 首先需要创建logging的配置文件&#xff0c;我是放在项目根目录的&#xff0c; Logging 配置 logging.json {"version": 1, # 配置文件版本号"formatters": {"default&qu…

HTTP 协议和 TCP/IP 协议之间有什么区别?

HTTP&#xff08;超文本传输协议&#xff09;和TCP/IP&#xff08;传输控制协议/互联网协议&#xff09;是两种在互联网通信中广泛使用的协议&#xff0c;它们之间的区别和联系对许多人来说可能还不是很清晰&#xff0c;今天我们就带大家来一起了解一下HTTP和TCP/IP协议这2者之…

java数据结构与算法刷题-----LeetCode566. 重塑矩阵

java数据结构与算法刷题目录&#xff08;剑指Offer、LeetCode、ACM&#xff09;-----主目录-----持续更新(进不去说明我没写完)&#xff1a;https://blog.csdn.net/grd_java/article/details/123063846 文章目录 1. 法一&#xff0c;下标填充2. 法二&#xff1a;数学除法和取余…

MFC 序列化机制

目录 文件操作相关类 序列化机制相关类 序列化机制使用 序列化机制执行过程 序列化类对象 文件操作相关类 CFile&#xff1a;文件操作类&#xff0c;封装了关于文件读写等操作&#xff0c;常见的方法&#xff1a; CFile::Open&#xff1a;打开或者创建文件CFile::Write/…