美文网首页KotlinGradle
全网首套, 手把手教你学会gradle

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

作者: 黑马程序员小华华 | 来源:发表于2017-09-19 11:21 被阅读807次

    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

    相关文章

      网友评论

        本文标题:全网首套, 手把手教你学会gradle

        本文链接:https://www.haomeiwen.com/subject/mzwbsxtx.html