Gradle是地表最强的自动化构建系统
综合效率是maven的100倍
Kotlin又是最好用的jvm平台的编程语言
他们在一起会发生什么样的故事呢?
本课程是国内全网第一套基于kotlin语法讲解的gradle教程。
Kotlin强大的静态语言特性, 让你可以脱离文档直接编写gradle脚本
无论你是安卓程序员还是JavaEE程序员都有必要学习一下这门课程.
第1节 gradle入门
1.1 gradle配置
下载gradle:https://gradle.org/install/
解压,bin目录配置到path环境变量
1.2 创建gradle工程
idea创建gradle工程,选择java工程
输入包名、项目名称
1.3配置本地gradle
gradle-wrapper.properties配置本地gradle
build.gradle重命名后缀添加.kts(可以使用kotlin编写gradle脚本)
一定要记得, 重启idea配置生效
1.4 gradle入门编程
编写gradle.gradle.kts
plugins { application }
application { mainClassName="Main"}
Main.java类代码
public class Main {
public static void main(String[] args) {
System.out.println("hello");
}
}
运行:点击右边tasks/application/run,运行,输出hello
1.5没有src目录问题解决
官方文档
https://intellij-support.jetbrains.com/hc/en-us/community/posts/206806425-Source-Directories-Not-Being-Created-In-New-Project
1.6 application/run没有看到输出结果问题的解决
第2节 Kotlin与Java共存
gradle与kotlin相见恨晚:https://blog.gradle.org/kotlin-meets-gradle
动态语言:python、groovy、JavaScript(运行时才检查错误)
静态语言:Kotlin、Java(编译阶段能发现错误)
演示Java调用kotlin代码
2.1 build.gradle.kts配置
gradle-wrapper.properties配置成本地gradle
plugins {
application
kotlin("jvm")
}
application{
mainClassName="Test"
}
dependencies {
compile(kotlin("stdlib"))
}
repositories{
jcenter()
}
2.2 Kotlin代码
class Girl(var name:String) {
fun greeting(){
println("你好,"+name)
}
}
2.3 Java调用Kotlin
public class Test {
public static void main(String[] args) {
Girl girl = new Girl("刘菲菲");
girl.greeting();
}
}
第3节 gradle的灵魂project和task
Gradle本身的领域对象主要有Project和Task。
Project位Task提供执行的容器和上下文。
编写自己的任务,build.gradle.kts代码
task("hello",{
println("hello, I am gradle")
})
第4节 任务的依赖
打开冰箱门,才能放入大象,然后关门
task("opendoor", {
})
task("putelephant", {
}).dependsOn("opendoor")
task("closedoor", {
}).dependsOn("putelephant")
//运行关冰箱门,输出结果
:opendoor UP-TO-DATE
:putelephant UP-TO-DATE
:closedoor UP-TO-DATE
第5节 gradle任务的生命周期
gradle任务分为:扫描时执行、运行时执行
5.1 扫描时执行
执行opendoor三个任务都执行,因为是扫描时任务
task("opendoor", {
println("打开冰箱门")
})
task("putelephant", {
println("放入大象")
}).dependsOn("opendoor")
task("closedoor", {
println("关闭冰箱门")
}).dependsOn("putelephant")
5.2 运行时执行doFirst
task("opendoor", {
doFirst { println("打开冰箱门") }
})
task("putelephant", {
doFirst {println("放入大象") }
}).dependsOn("opendoor")
task("closedoor", {
doFirst { println("关闭冰箱门") }
}).dependsOn("putelephant")
5.3 总结扫描时运行时
一般在扫描doFirst外部声明变量,内部编写任务
task("login",{
val username = "heima"
val password = "123"
doFirst {
if("heima" == username && "123" == password) println("登录成功")
else println("登录失败")
}
})
第6节 gradle任务集
任务的集合
tasks{
"opendoor"{
doFirst { println("打开冰箱门") }
}
"putelephant"{
doFirst { println("放入大象") }
}.dependsOn("opendoor")
"closedoor"{
doFirst { println("关闭冰箱门") }
}.dependsOn("putelephant")
}
第7节 默认属性
gradle默认自带一些属性,比如构建路径,配置文件等待,
打印gradle默认配置信息
task("showConfig",{
//project:默认工程,properties是工程属性Map集合
project.properties.forEach { t, any ->
println("key="+t+",value="+any)
}
})
输出结果:
第8节 默认任务
控制台输入gradle执行默认任务,不需要指定任务名称
task("showConfig",{
//project:默认工程,properties是工程属性Map集合
project.properties.forEach { t, any ->
println("key="+t+",value="+any)
}
})
//执行默认任务
defaultTasks("showConfig")
第9节 编写gradle增量式更新任务
增量式更新:哪个文件改变,才更新哪个
gradle增量式更新任务效率是maven的100倍
需求:遍历src目录下源代码文件明,输出到info.txt
9.1 不使用增量更新遍历文件
build.gradle.kts代码:
plugins { java }
task("showSrcDir",{
//获取遍历src目录下的文件
val fileTree = fileTree("src")
val infoFile = file("info.txt")
infoFile.writeText("")//清空数据
fileTree.forEach {
if(it.isFile){
//拼接,写入文件
Thread.sleep(1000)//为了演示增量更新效率
infoFile.appendText(it.absolutePath+"\r\n")
}
}
})
9.2 使用增量式更新
inputs.dir() //输入目录
inputs.file() //输入文件
outputs.dir() //输出目录
outputs.file() //输出文件
没有变化,执行0秒
plugins { java }
task("showSrcDir",{
//如果src目录下内容和info.txt没有发生改变,任务不会执行
inputs.dir("src") //输入目录
outputs.file("info.txt")//输出文件
doFirst {
//获取遍历src目录下的文件
val fileTree = fileTree("src")
val infoFile = file("info.txt")
infoFile.writeText("")//清空数据
fileTree.forEach {
if(it.isFile){
//拼接,写入文件
Thread.sleep(1000)
infoFile.appendText(it.absolutePath+"\r\n")
}
}
}
})
修改src目录下Java源代码,重新执行,2秒钟
public class Student {
//新增
private String name = "heima";
}
第10节 gradle常见插件application,java
application插件:可以编写java工程、kotlin工程
java插件:只能编写java代码
常用插件:https://docs.gradle.org/4.1/userguide/userguide.html
gradle所有插件:https://plugins.gradle.org/
//使用application插件
plugins { application }
//配置插件
application {
//设置主函数
mainClassName = "Girl"
}
第11节 gradle依赖管理入门(普通程序员的开发流程)
需求:使用http-client 3.1实现下载图片功能
图片路径:http://img1.mm131.com/pic/946/1.jpg, …后面xxx/2.jpg依次类推
普通程序员一般百度http-client 3.1,然后下载jar包,
11.1下载http-client3.1jar包
下载地址:百度...
使用文档:百度...
代码:
//下载图片
val httpClient = HttpClient()
val method = GetMethod("http://img1.mm131.com/pic/946/1.jpg")
httpClient.executeMethod(method)
val responseBody = method.getResponseBody();
//输出文件
var file = File("1.jpg")
file.writeBytes(responseBody)
11.2 下载commons-logging.jar
上面代码运行报错
Exception in thread "main" java.lang.NoClassDefFoundError: org/apache/commons/logging/LogFactory
at org.apache.commons.httpclient.HttpClient.(HttpClient.java:65)
at DownloaderKt.main(Downloader.kt:9)
Caused by: java.lang.ClassNotFoundException: org.apache.commons.logging.LogFactory
at java.net.URLClassLoader.findClass(Unknown Source)
at java.lang.ClassLoader.loadClass(Unknown Source)
at sun.misc.Launcher$AppClassLoader.loadClass(Unknown Source)
at java.lang.ClassLoader.loadClass(Unknown Source)
... 2 more
普通程序员百度,找到下载地址http://vdisk.weibo.com/s/z0am_ebTNl0Zp,下载添加到项目中
11.3 下载commons-codec.jar
上面代码运行报错
Exception in thread "main" java.lang.NoClassDefFoundError: org/apache/commons/codec/DecoderException
at org.apache.commons.httpclient.HttpMethodBase.(HttpMethodBase.java:217)
at org.apache.commons.httpclient.methods.GetMethod.(GetMethod.java:88)
at DownloaderKt.main(Downloader.kt:9)
Caused by: java.lang.ClassNotFoundException: org.apache.commons.codec.DecoderException
at java.net.URLClassLoader.findClass(Unknown Source)
at java.lang.ClassLoader.loadClass(Unknown Source)
at sun.misc.Launcher$AppClassLoader.loadClass(Unknown Source)
at java.lang.ClassLoader.loadClass(Unknown Source)
... 3 more
普通程序员百度,发现需要下载commons-codec.jar,然后下载添加到项目中
最终下载完成15张图片
//下载15张图片图片
val range = 1..15
for (i in range) {
val httpClient = HttpClient()
val method = GetMethod("http://img1.mm131.com/pic/946/${i}.jpg")
httpClient.executeMethod(method)
val responseBody = method.getResponseBody();
method.releaseConnection();
//输出文件
var file = File("${i}.jpg")
file.writeBytes(responseBody)
}
第12节 gradle依赖管理(高级程序员如何添加依赖)
高级程序员使用依赖管理,不需要手动下载jar包。
12.1 http-client maven仓库
百度:http-client 3.1 maven,找到http-client的maven仓库,
12.2 build.gradle.kts配置
plugins{
application
kotlin("jvm")
}
apply {
plugin("kotlin")
}
application {
mainClassName = "DownloaderKt"
}
dependencies {
compile(kotlin("stdlib"))
compile("commons-httpclient","commons-httpclient","3.1")
}
repositories {
mavenCentral()
jcenter()
}
12.3 kotlin代码
//下载15张图片图片
val range = 1..15
for (i in range) {
val httpClient = HttpClient()
val method =
GetMethod("http://img1.mm131.com/pic/946/${i}.jpg")
httpClient.executeMethod(method)
val responseBody = method.getResponseBody();
method.releaseConnection();
//输出文件
val file = File("${i}.jpg")
file.writeBytes(responseBody)
}
12.4 run出现找不到主类问题的解决
我的Kotlin文件名:Downloader.kt
build.gradle.kts配置运行主类:Downloader
运行报错:找不到或无法加载主类 Downloader
解决:运行kotlin主类,需要在类名后带上Kt
application { mainClassName = "DownloaderKt"}
第13节 gradle依赖管理的类比
普通程序员百度查找解决方案,下载http-client.jar,错误然后百度下载commons-logging.jar和commons-codec.jar,这种开发效率很低,而且有个jar包可能依赖很多个jar包
高级程序员通过依赖管理,只需一个依赖,其他相关commons-logging和commons-codec都会自定依赖到项目中,这就是gradle依赖管理的优势。
第14节
公共仓库和依赖配置阶段
依赖管理:指在什么地方以什么形式引入外部代码。
14.1 常用2个公共仓库
公共仓库:
maven center:http://mvnrepository.com/
jcenter:https://bintray.com/bintray/jcenter
14.2 测试时依赖
依赖分为两种:
编译时依赖:compile
测试时依赖:testcompile,只在测试阶段使用,项目打包上线不依赖。
build.gradle.kts添加测试依赖
maven仓库:http://mvnrepository.com/artifact/junit/junit/4.12
…省略…
dependencies {
compile(kotlin("stdlib"))
//testCompile
group: 'junit', name: 'junit', version: '4.12'
//测试时依赖
testCompile("junit","junit","4.12")
}
repositories {
mavenCentral()
jcenter()
}
运行结果:注意,测试类代码在src/main/test/java中,或者src/main/test/kotlin
第15节 gradle依赖冲突的解决
15.1 什么是冲突
BOSS:我需要AB来帮我干活
A:我需要老王1.0版本来干活
B:我需要老王1.2版本来干活
BOSS:晕了
调用老王.开发()的方法
究竟执行的是老王1.0版本还是老王1.2版本干活呢?
15.2 gradle自动依赖最高版本
第12节项目中,http-client依赖logging版本1.0.4,对该项目添加spring 4.3.9依赖,发现loggin版本变成1.2
15.3 手动解决依赖冲突
高版本logging1.2理论上兼容1.0.4版本,gradle会自动解决版本兼容问题,但是特殊情况,可能会出现冲突。
假如,我们希望保留http-client依赖的loggin 1.0.4版本,可以在compile spring依赖中添加闭包,让spring去除loggin依赖,运行前面的下载美女图片任务,也没有问题
所以,以后遇到依赖冲突问题。可以exclude取消其他项目依赖,保留一个即可。
第16节
gradle插件自定义扩展
16.1介绍
扩展任务:扩展系统自带的任务,原来扩展任务这么方便。
官方文档:https://docs.gradle.org/current/dsl/index.html
16.2 扩展copy任务
演示扩展系统copy任务
文档:https://docs.gradle.org/current/dsl/org.gradle.api.tasks.Copy.html
task("mycopy", Copy::class, {
//src/main/java目录下文件拷贝到 src/main/temp
from("src/main/java")
into("src/main/temp")
})
16.2 扩展delete任务
演示删除src/main/temp目录下文件
task("mydelete", Delete::class, {
setDelete("src/main/temp")
})
16.3 扩展jar任务
演示把java文件打成jar包
task("myjar", Jar::class, {
//把src/main/java打成jar包到 myjar目录
from("src/main/java")
archiveName = "myjar/a.jar"
})
第17节 gradle调用外部扩展
演示:Kotlin调用java代码
为什么:以后开发,可能以前用Java写好了某些功能,现在直接使用Kotlin调用即可。
17.1 编译java
点击右侧compileJava编译Java文件成class
Java代码
public class Girl {
public static void main(String[] args) {
System.out.println("我是美女");
}
}
17.2 kotlin任务调用Java
把上面编译生成的Girl.class保存到项目根目录
buid.gradle.kts代码:
plugins { application }
task("callJava", {
javaexec {
//java主类
main = "Girl"
//根目录下
classpath(".")
}
})
运行callJava任务,输出:我是美女。成功调用java代码
第18节 gradle的学习方法
如果大家仔细学会了上面的内容, 基本上就成为国内第一批 用kotlin语法编写gradle脚本的程序员.大家可以看到百度搜索只有16个相关文章,用kotlin编写gradle一定是以后的趋势, groovy这种动态语言的语法,是有先天的不足的...
其实掌握学习方法比知识点重要:
1.保持技术敏感度、经常关注gradle技术博客https://blog.gradle.org/,官方技术博客可以获取第一手资料。
2.kotlin编写gradle示例代码:https://github.com/gradle/kotlin-dsl/tree/master/samples#readme
3.CTO也是从普通开发人员慢慢成长而来,CTO具备技术前瞻性,保持技术敏感度,日积月累。未来,大家也能够成长为技术大牛。
文章比较长, 看起来比较累的话欢迎去看腾讯课堂的视频, 大部分课程可以试学,
如果您觉得内容有帮助希望能购买一下课程, 19.9元,每卖出一套我能分到2块钱, 就当请我喝一瓶农夫山泉吧. _
腾讯课堂教程配套视频: https://ke.qq.com/course/235231