【Gradle构件工具深度学习】

Gradle构件工具深度学习

  • 1. 课程大纲
    • 1.1 Gradle入门
    • 1.2 与Idea整合
    • 1.3 Gradle进阶
  • 2. 常见项目构建工具
  • 3. 安装gradle
  • 4. gradle常用指令
  • 5. 拓展:init.gradle文件说明 | 仓库地址说明
  • 6. Wrapper包装器
    • 6.1 是什么?
    • 6.2 使用gradle wrapper
    • 6.3 什么时候使用gradle?什么时候使用gradle wrapper?
  • 7. Gradle与IDEA整合
    • 7.1 Groovy简介
    • 7.2 build.gradle中执行任务Task
    • 7.3 任务执行
      • 7.3.1 常见任务
      • 7.3.2 项目报告相关任务
      • 7.3.3 调试相关选项
      • 7.3.4 性能选项[在gradle.properties中指定这些选项中的许多选项,因此不需要命令行标记]
      • 7.3.5 日志相关
    • 7.4 任务定义方式
    • 7.5 任务的属性
    • 7.6 任务类型
    • 7.7 任务属性
    • 7.8 任务规则(当这个任务不存在的时候,就会执行这个规则的闭包,不影响其他task)
    • 7.9 任务断言onlyIf
    • 7.10 默认任务,在编译的时候自动指定
    • 7.11 文件操作
    • 7.12 归档文件
    • 7.13 依赖
      • 7.13.1 依赖的类型,和maven中的scope类似
      • 7.13.2 api 与 implement的区别
      • 7.13.3 依赖冲突及解决方案
  • 8. Gradle插件
    • 8.1 使用插件的原因
    • 8.2 插件的作用
    • 8.3 插件的分类和使用

1. 课程大纲

1.1 Gradle入门

基本介绍、常用指令、项目目录、项目应用

1.2 与Idea整合

Groovy语法、整合IDEA、搭建web工程、项目部署

1.3 Gradle进阶

生命周期、钩子函数、项目发布、配置文件、Project与Task、Gradle插件
整合SSM多模块、微服务实战

2. 常见项目构建工具

Ant:2000Apache推出的纯Java编写构建工具,通过xml build.xml文件管理项目
	优点:使用灵活,速度快(快于gradle和maven),
	缺点:At没有强加任何编码约定的项目目录结构,开发人员需编写繁杂XL文件构建指令对开发人员是一个
			挑战。
Maven: 2004Apache组织推出的再次使用xml文件pom.xml虹管理项目的构建工具.
	优点:遵循一套约定大于配置的项目目录结构,使用统一的GAV坐标进行依赖管理,侧重于包管理。
	缺点:项目构建过程僵化.配置文件编写不够灵活、不方便自定义组件构建速度慢于d!e,
Gradle:2012Google推出的基于Groovy语言的全新项目构建工具,集合了AntMaven各自的优势。
	优点:集Ant脚本的灵活性+Mavn约定大于配置的项目目录优势,支持多种远程仓库和插件,侧重于大项目
		构建。
	缺点:学习成本高、资料少、脚本灵活、版本兼容性差等。

【Gradle构件工具深度学习】_第1张图片

3. 安装gradle

  1. 下载gradle
    官网地址(点击此处跳转):https://gradle.org/releases/
  2. 推荐下载红色圈住的,带有源码
    【Gradle构件工具深度学习】_第2张图片
  3. 解压到指定目录下,然后复制此路径,配置环境变量
  4. 4.新建系统变量[GRADLE_HOMW=$你复制的路径];将%GRADLE_HOME%\bin添加到PATH环境变量下,然后点击确定
  5. 校验配置是否生效,cmd下执行gradle -v ,如果打印出gradle版本以及JVM厂商信息就说明success!
  6. 配置gradle本地仓库地址:新建系统环境变量 [GRADLE_USER_HOME=$你的maven仓库地址]
  7. 配置阿里云镜像地址:在gradle,init.d目录下新建一个init.gradle文件,并在文件中添加如下配置:
allprojects {
	repositories {
    	mavenLocal()
		maven {name "Alibaba" ; url 'https://maven.aliyun.com/repository/public'}
		maven {name "Bstek" ; url "https://nexus.bsdn.org/content/groups/public/"}
		mavenCentral()
	}
	buildscript {
		repositories {
		maven {name "alibaba"; url :"https://maven.aliyun.com/repository/public "}
		maven {name  "Bstek" ; url "https://nexus.bsdn.org/content/groups/public/"}
		maven {name "M2" ; url "https://plugins.gradle.org/m2/"}
	}
}

4. gradle常用指令

常用gradle指令 作用
gradle clean 清空build目录
gradle classes 编译业务代码和配置文件
gradle test 编译测试代码,生成测试报告
gradle build 构建项目
gradle build -x test 跳过测试构建项目

注意:gradle的指令要在含有build.gradle的目录执行。

5. 拓展:init.gradle文件说明 | 仓库地址说明

init.gradle可以在编译启动前执行这个脚本,比如配置上镜像地址

有几种方式使用init.gradle呢

1.	在命令行指定文件,例如: gradle --init-script yourdir/init.gradle -q taskName.你可以多次输入此命
	令来指定多个init文件
3.	把init.gradle文件放到USER_HOME/,gradle/目录下
4.	把以.gradle结尾的文件放到USER_HOME/.gradle/init.d/目录下
5.	把以.gradle结尾的文件放到GRADLE_HOME/init.d目录下
如果存在上面的4种方式的2种以上,gradle会按上面的1-4序号依次执行这些文件,如果给定目录下存在多个
init脚本,会按拼音a-z顺序执行这些脚本,每个nit脚本都存在一个对应的adle实例,你在这个文件中调用的
所有方法和属性,都会委托给这个gradle实例,每个init脚本都实现了Seript接口。

仓库地址说明:

mavenLocal():指定使用本地maven本地仓库,而本地仓库在配置maven时settings文件指定的仓库位置。
maven {url位置},指定maven仓库,一般用私有仓库地址或其他第三方库。比如阿里云镜像地址
mavenCentral() 这是Maven的中央仓库,无需配置,直接声明就可以使用。
jcenter(): Jcenter中央仓库,实际也是用的maven搭建,但相比Maven仓库更友好,通过cdn分发,并且支持https访问,在新版本中已经废弃,替换为了mavenCentral()

总之,gradle可以通过指定仓库地址为本地maven仓库地址和远程仓库地址相结合的方式,避免每次都会去远程仓库下载依赖库·这种方式也有一定的问题,如果本地maven仓库有这个依赖,就会从直接加载本地依赖,如果本地仓库没有该依赖,那么还是会从远程下载·但是下载的jar不是存储在本地naven仓库中,而是放在自己的缓存目录中,默认在USER_HOME/.gradle/caches目录,当然如果我们配置过GRADLE_USER_HOME环境变量,则会放在GRADLE_USER_HOME/caches目录,那么可不可以将gradle caches指向maven repository。我们说这是不行的,caches下载文件不是按照maven仓库中存放的方式·

阿里云开发者镜像查询地址:https://developer.aliyun.com/mvn/guide

6. Wrapper包装器

6.1 是什么?

Gradle Wrapper实际上就是对Gradle的一层包装,用于解快实际开发中可能会遇到的不同的项目需要不同版本的Gradle问题。例如:把自己的代码共享给其他人使用,可能出现如下情况:

  • 对方电脑上没有安装gradle
  • 对方电脑上安装了gradle,但是版本太旧了

这时候,我们就可以考虑使用Gradle Wrapper了。这也是官方建议使用Gradle Wrapper的原因。实际上有了Gradle Wrapper之后,我们本地是可以不配置Gradle的,下载Gradle项目后,使用gade项目自带的wrapper操作也是可以的。

6.2 使用gradle wrapper

项目中的gradlew gradlew.cmd脚本用的就是wrapper中规定的gradle版本·参见源码
而我们上面提到的g红adle指令用的是本地gradle, 所以gradle指令和gradlew指令所使用的gradle版本有可能是不一样的
gradlew gadlew.cmd的使用方式与gradle使用方式完全一致,只不过把g红adle指令换成了gradlew指令。

当然我们也可在终端执行gradlew指令时,指定指定一些参数,来控制Wrapper的生成,比如依赖的版本等,如下:

参数 说明
–gradle-version 用于指定使用的gradle版本
–gradle-distribution-url 用于指定下载gradle发行版url地址

执行gradle wrapper --gradle-version=7.4.2 --gradle-distribution-url=地址

6.3 什么时候使用gradle?什么时候使用gradle wrapper?

下载别人的项目或者使用操作以前自己写的不同版本的gradle项目时:用Gradle wrapper,也即gradew
什么时候使用本地gradle?新建一个项目时:使用gradle指令即可。

7. Gradle与IDEA整合

7.1 Groovy简介

在某种程度上,Groovy可以被视为Java的一种脚本化改良版,Groovy也是运行在JVM上,它可以很好地与Java代码
及其相关库进行交互操作。它是一种成熟的面向对象编程语言,既可以面向对象编程,又可以用作纯粹的脚本语言。
大多数有效的Java代码也可以转换为有效的Groovy代码,Groovy和Java语言的主要区别是:完成同样的任务所需的
Groovy代码比Java代码更少。其特点为:
>	功能强大,例如提供了动态类型转换、闭包和元编程(metaprogramming)支持
> 支持函数式编程,不需要main函数
> 默认导入常用的包
> 类不支持default作用域,且默认作用域为public。
> Groovy中基本类型也是对象,可以直接调用对象的方法。
> 支持DSL(Domain Specific Languages领域特定语言)和其它简洁的语法,让代码变得易于阅读和维护。
> Groovy是基于Java语言的,所以完全兼容Java语法,所以对于Java程序员学习成本较低。

详细了解参考官网. 官网地址http://www.groovy-lang.org/documentation.html

7.2 build.gradle中执行任务Task

Task "task1" {
	println "弟弟你真好"
	doFirst {
		println "弟弟身材真好"
	}
	doLast {
		println "弟弟的腰 杀人的刀"
	}
}

Task "Task2" {
  doLast {
		println "姐姐喜欢细狗"	
 }
}

Task2.dependsOn=['task1']

任务执行: gradle taskName, eg: gradle -i c 执行任务c
重复依赖的任务只执行一次

7.3 任务执行

7.3.1 常见任务

  1. gradle build:编译测试打包
  2. gradle run:运行一个服务,需要application插件支持,并且指定了主启动类才能运行
  3. gradle clean: 清空当前项目的build目录
  4. gradle init :初始化项目使用
  5. gradle wrapper:生成wrapper文件夹的

7.3.2 项目报告相关任务

  1. gradle projects 列出所选项目及子项目列表,以层次结构显示
  2. gradle tasks 列出所选项目【不包含父子】的分配给任务组的哪些项目
  3. gradle tasks --all 列出所选项目的所有任务
  4. gradle tasks --group=“build setup” 列出所选项目中指定分组的任务
  5. gradle help --task someTask 显示某个任务的详细信息
  6. gradle dependencies 查看整个项目的依赖信息,以依赖树的方式显示
  7. gradle properties 列出所选项目的属性列表
task task2(dependsOn:['task1']) {
    group("abc") // 将任务task2添加到任务组abc
    doLast {
        println "task2 last"
    }
}

//查看某个任务组下的任务列表
gradle tasks --group="abc" 查看任务组abc的任务

7.3.3 调试相关选项

-h, --h 查看帮助信息
-v,–version 打印Gradle、Groovy、Ant、JVM和操作系统版本信息
-S, --full-stacktrace 打印出用户异常的堆栈跟踪 例如编译错误
-Dorg.gradle.daemon.debug=true 调试Gradle守护进程
-Dorg.gradle.debug=true 调试Gradle客户端(非daemon)进程
-Dorg.gradle.debug.port=port_number 指定启用调试时要监听的端口,默认是5005

gradle,properties.里面定义的属性是全局的,可以在各个模块的build.gradle里面直接引用,
当有一些数据我们传到git又不想给别人看的时候,就可以配置到gradle,properties,然后不传这个文件上去
也可以在项目中对一些属性进行统一配置,提高开发效率

【Gradle构件工具深度学习】_第3张图片

7.3.4 性能选项[在gradle.properties中指定这些选项中的许多选项,因此不需要命令行标记]

–build-cache,-no-build-cache:尝试重用先前版本的输出。默认关闭(off)
–max-workers::设置Gradle可以使用的woker数。默认值是处理器数。
-parallel,.-no-parallel:并行执行项目。有关此选项的限制,请参阅并行项目执行。
默认设置为关闭(off)

7.3.5 日志相关

-Dorg.gradle.logging.level=(quiet,warn,lifecycle,info,debug): 通过Gradle属性设置日志记录级别。
-q,一quiet:只能记录错误信息
-w,-warm:设置日志级别为warn
-i,-info:将日志级别设置为info
-d,一debug:登录调试模式(包括正常的堆栈跟踪)
-x:-x等价于:-exclude-.task: 常见gradle-x test clean build
-rerun-tasks: 强制执行任务,忽略up-to-date,常见gradle build-rerun-tasks
-continue:忽略前面失败的任务继续执行,而不是在遇到第一个失败时立即停止执行。每
个遇到的故障都将在构建结束时报告,常见:gradle build --continue.
gradle init --type pom将maven项目转换为gradle项目根目录执行
gradle [task Name] -执行自定义任务

7.4 任务定义方式

Project中的task()方法,另一种是通过tasks对象的create或者register方法。

task('A', {				// 任务名称,闭包都作为参数
	println "taskA...."
})
task('B') {			// 闭包作为最后一个参数可以直接从括号中拿出来
	println "taskB..."
}

task C{	// groovy语法支持省略方法括号
	println "taskC..."
}

def map = new HashMap();
map.put("action",{println "taskD..."}); //action属性可以设置为闭包
task(map,"D");
tasks.create("E"){ 		//使用tasks的create方法
	println "taskE..."
}

tasks.register('f'){ // 注: register执行的是延迟创建,也即只有task被需要使用的时候才会被创建。
	println "taskF..."
}

7.5 任务的属性

type: 基于一个存在的Tsk来创建,和我们类继承差不多。 默认值:DefaultTask
overwrite:是否替换存在的Task,这个和type配合起来用 默认值:false
dependsOn:用于配置任务的依赖 默认值:[]
action:添加到任务中的一个Action或者一个闭包。默认值:null
description:用于配置任务的描述。默认值:null
group:用于配置任务的分组。默认值:null

task("task3",description: "this is task3",group:"abc") {
    doLast({
        println "task3 ..."
    })

}

task("task4"){
    group("abc")
    description("this is the task H")

}

7.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 组装TAR存档文件
Test 执行Junit或TestNG测试
Upload 将Configuration的构件上传到一组存储库
War 组装War归档
Zip 组装ZIP归档文件。默认是压缩ZIP的内容

提示1:gradle自带Task类型,参考官方文档
提示2:官方文档给出这些类型的时候,同时给出了案例代码,可以直接去上述官网的某个类型中观看

7.7 任务属性

  • 任务开启:task.enable=false
  • 任务超时:task.timeout=Duration.ofMills(500)
  • 任务跳过继续执行:gradle task1 task2 --continue

7.8 任务规则(当这个任务不存在的时候,就会执行这个规则的闭包,不影响其他task)

tasks.addRule(“rule desc”) {
String taskName -> task(taskName) {
println “the $taskName is not exist”
}
}

7.9 任务断言onlyIf

task hello {
	doLast {
		println "hello 粉丝们"
	}
}
hello.onlyIf( !project.hasProperty('fensi'))
//没有这个属性 就会执行这个hello任务
> gradlew.bat hello
> hello 粉丝粉
> gradlew.bat hello -Pfensi //-P在根项目下添加属性

7.10 默认任务,在编译的时候自动指定

defaultTasks 'myClean', 'myRun'

tasks.register('myClean') {
    doLast {
        println 'Default cleaning!'
    }
}
tasks.register('myRun') {
    doLast {
        println 'Default Running!'
    }
}
tasks.register('other') {
    doLast {
        println "I'm not a default task!"
    }
}

似乎没有起作用,可能与版本有关系。

7.11 文件操作

// 使用本地文件的操作方式:相对路径
def file = file('D:/yuan.txt')
//file.createNewFile();
//file.write("spring source successfully")

//file.delete()
def fileCollection = files('src/text1.txt', 'src/tt.xml')
def fileSet = fileCollection as Set
def lists = fileCollection as List
def ff = fileCollection + lists
fileCollection.forEach { item -> println item.getName() }
Set<File> aa = fileCollection.files

// 文件树
def fileTree = fileTree('src/main')
fileTree.exclude("**/**.java").forEach { item -> println item }
//文件拷贝
task copyTask(type:Copy){
    from 'src/main/resources'
    into 'build/config'
}

// 文件复制
// 方式一:自定义任务
// 方式二: Project的copy方法

7.12 归档文件

通常一个项目会有很多的Jar包,我们希望把项目打包成一个WAR,ZIP或TAR包进行发布,这时我们就可以使用
Zip,Tar,Jar,War和Ear任务来实现,r不过它们的用法都一样,所以在这里我只介绍Zip任务的示例。首先,创建
一个Z即压缩文件,并指定压缩文件名称,如下代码所示:

7.13 依赖

/**
*依赖方式:
* 本地依赖 依赖本地的某个jar包,具体通过文件集合 文件树的方式指定
* 项目依赖:依赖某个project
* 直接依赖:依赖的类型、依赖的组名、依赖的名称、依赖的版本号
*/

dependencies {
    // 本地依赖-文件集合/文件树
    implementation files('lib/mysql.jar','lib/log4j.jar')
    // 项目依赖
    implementation project(":spring-jdbc")
    // 直接依赖
    implementation 'mysql:mysql-connector-java:8.0.23'
    // 完整写法
    implementation group: 'mysql', name: 'mysql-connector-java', version: '8.0.33'
}

7.13.1 依赖的类型,和maven中的scope类似

  • compileOnly: 由java插件提供,曾短暂的叫provided,后续版本已经改成了compileOnly,适用于编译期需要而不需要打包的情况(比如servlet-api,只在编译时需要)
  • runtimeOnly: 由java插件提供,只在运行期有效编译时不需要,比如mysgl驱动包。取代老版本中被移除的runtime(mysql驱动)
  • implementation: java插件提供针对源码src/main目录,在编译、运行时都有效,取代老版本中被移除的compile。(编译运行都有效)
  • testCompileOnly: 由java插件提供,用于编译测试的依赖项,运行时不需要
  • testRuntimeOnly: 由java插件提供,只在测试运行时需要,而不是在测试编译时需要,取代老版本中被移除的testRuntime
  • testImplementation: 由java插件提供,针对测试代码rsrc/test目录】取代老版本中被移除testCompile
  • provideCompile:war插件提供支持,编译、测试阶段代码需要依赖此类jar包,而运行阶段容器已经提供了相应的支持,所以无需将这些文件打入到war包中了,例如servlet-.api.jar、isp-api.jar
  • compile:编译范画依赖在所有的classpath中可用,同时它们也会被打包。在ggadl山e7.0已经除
  • runtime:runtime依赖在运行和测试系统的时候需要,在编译的时候不需要,比如mysql驱动包。在gradle7.0已经移除
  • api: java–library插件提供支持这些依赖项可以传递性地导出给使用者,用于编译时和运行时。取代老版本中被移除的compile
  • compileOnlyApi: java–library插件提供支持在声明模块和使用者在编译时需要的依赖项,但在运行时不需要

7.13.2 api 与 implement的区别

api implement
编译时 能进行依赖传递,底层变,全部都要变,编译速度慢 不能进行依赖传递,底层变,不用全部都要变,编译速度快
运行时 运行时会加载,所有模块的class都要被加载 运行时会加载,所有模块的class都要被加载
应用场景 适用于多模块依赖,避免重复依赖模块 多数情况下使用implementation

7.13.3 依赖冲突及解决方案

依赖冲突是指"在编译过程中,如果存在某个依赖的多个版本,构建系统应该选择哪个进行构建的问题",如下所示:


dependencies {
	testImplementation 'org.junit jupiter:junit-jupiter-api:5.8.1'
	testRuntimeOnly 'org junit jupiter:junit-jupiter-engine:5.s.1'
	implementation('org.hibernate:hibernate-core:3.6.s.Final) {
	//排除某一个库(s1f)依赖:如下三种写法都行
		exclude group:'org.slftj
		exclude module:'slftj-api'
		exclude group:'org.slftj,module:'slftj-api
	} 
	//排除之后,使用手动的引入即可
	implementation 'org.slftj:slftj-api:1.4.0'
}

// 还有一种方式就是:
transitive(false)

// 强制使用某个版本
implementation ('org.slf4j:slf4j-api:1.4.0'){
	version{
		strictly("1.4.0")
}
或者
implementation ('org.slf4j:slf4j-api:1.4.0!!')

如果遇到冲突报错,否则默认采用最新的版本解决冲突
//下面我们配置,当Gradle构建遇到依赖冲突时,就立即构建失败
configurations.all() {
	Configuration configuration ->
	//当遇到版本冲突时直接构建失败
	configuration.resolutionStrategy.failonVersionConflict()
}

8. Gradle插件

8.1 使用插件的原因

简单的说,通过应用插件我们可以:

1. 促进代码重用、减少功能类似代码编写、提高工作效率
2. 促进项目更高程度的模块化、自动化、便捷化
3. 可插拔的扩展项目的功能

8.2 插件的作用

在项目构建过程中做很多事情,把插件应用到项目中,通常可以完成:

  1. 可以添加任务task到项目中,从而帮助完成测试,编译、打包等
  2. 可以添加依赖配置到项目中
  3. 可以向项目中扩展新的扩展属性、方法等
  4. 可以对项目进行一些约定。如应用java插件后,约定src/main/java目录是我们的源代码存在的位置,编译时编译这个目录下的java源代码文件。

8.3 插件的分类和使用

  1. 脚本插件
  2. 二进制插件(对象插件)
    1. 内部插件
    2. 第三方插件
    3. 自定义插件

你可能感兴趣的:(#,Java,Gradle,Java)