全网首套, 手把手教你学会gradle

字数 2492阅读 1659

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工程

输入包名、项目名称

Paste_Image.png

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.<clinit>(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.<init>(HttpMethodBase.java:217)
at org.apache.commons.httpclient.methods.GetMethod.<init>(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

Paste_Image.png

第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

推荐阅读更多精彩内容