Gradle是地表最強(qiáng)的自動(dòng)化構(gòu)建系統(tǒng)
綜合效率是maven的100倍
Kotlin又是最好用的jvm平臺(tái)的編程語(yǔ)言
他們?cè)谝黄饡?huì)發(fā)生什么樣的故事呢?
本課程是國(guó)內(nèi)全網(wǎng)第一套基于kotlin語(yǔ)法講解的gradle教程。
Kotlin強(qiáng)大的靜態(tài)語(yǔ)言特性, 讓你可以脫離文檔直接編寫(xiě)gradle腳本
無(wú)論你是安卓程序員還是JavaEE程序員都有必要學(xué)習(xí)一下這門(mén)課程.
第1節(jié) gradle入門(mén)
1.1 gradle配置
下載gradle:https://gradle.org/install/

解壓,bin目錄配置到path環(huán)境變量


1.2 創(chuàng)建gradle工程
idea創(chuàng)建gradle工程,選擇java工程

輸入包名、項(xiàng)目名稱(chēng)



1.3配置本地gradle
gradle-wrapper.properties配置本地gradle
build.gradle重命名后綴添加.kts(可以使用kotlin編寫(xiě)gradle腳本)
一定要記得, 重啟idea配置生效

1.4 gradle入門(mén)編程
編寫(xiě)gradle.gradle.kts
plugins { application }
application { mainClassName="Main"}
Main.java類(lèi)代碼
public class Main {
public static void main(String[] args) {
System.out.println("hello");
}
}
運(yùn)行:點(diǎn)擊右邊tasks/application/run,運(yùn)行,輸出hello
1.5沒(méi)有src目錄問(wèn)題解決
官方文檔
https://intellij-support.jetbrains.com/hc/en-us/community/posts/206806425-Source-Directories-Not-Being-Created-In-New-Project

1.6 application/run沒(méi)有看到輸出結(jié)果問(wèn)題的解決

第2節(jié) Kotlin與Java共存
gradle與kotlin相見(jiàn)恨晚:https://blog.gradle.org/kotlin-meets-gradle
動(dòng)態(tài)語(yǔ)言:python、groovy、JavaScript(運(yùn)行時(shí)才檢查錯(cuò)誤)
靜態(tài)語(yǔ)言:Kotlin、Java(編譯階段能發(fā)現(xiàn)錯(cuò)誤)
演示Java調(diào)用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調(diào)用Kotlin
public class Test {
public static void main(String[] args) {
Girl girl = new Girl("劉菲菲");
girl.greeting();
}
}
第3節(jié) gradle的靈魂project和task
Gradle本身的領(lǐng)域?qū)ο笾饕蠵roject和Task。
Project位Task提供執(zhí)行的容器和上下文。
編寫(xiě)自己的任務(wù),build.gradle.kts代碼
task("hello",{
println("hello, I am gradle")
})

第4節(jié) 任務(wù)的依賴(lài)
打開(kāi)冰箱門(mén),才能放入大象,然后關(guān)門(mén)
task("opendoor", {
})
task("putelephant", {
}).dependsOn("opendoor")
task("closedoor", {
}).dependsOn("putelephant")
//運(yùn)行關(guān)冰箱門(mén),輸出結(jié)果
:opendoor UP-TO-DATE
:putelephant UP-TO-DATE
:closedoor UP-TO-DATE
第5節(jié) gradle任務(wù)的生命周期
gradle任務(wù)分為:掃描時(shí)執(zhí)行、運(yùn)行時(shí)執(zhí)行
5.1 掃描時(shí)執(zhí)行
執(zhí)行opendoor三個(gè)任務(wù)都執(zhí)行,因?yàn)槭菕呙钑r(shí)任務(wù)
task("opendoor", {
println("打開(kāi)冰箱門(mén)")
})
task("putelephant", {
println("放入大象")
}).dependsOn("opendoor")
task("closedoor", {
println("關(guān)閉冰箱門(mén)")
}).dependsOn("putelephant")
5.2 運(yùn)行時(shí)執(zhí)行doFirst
task("opendoor", {
doFirst { println("打開(kāi)冰箱門(mén)") }
})
task("putelephant", {
doFirst {println("放入大象") }
}).dependsOn("opendoor")
task("closedoor", {
doFirst { println("關(guān)閉冰箱門(mén)") }
}).dependsOn("putelephant")
5.3 總結(jié)掃描時(shí)運(yùn)行時(shí)
一般在掃描doFirst外部聲明變量,內(nèi)部編寫(xiě)任務(wù)
task("login",{
val username = "heima"
val password = "123"
doFirst {
if("heima" == username && "123" == password) println("登錄成功")
else println("登錄失敗")
}
})
第6節(jié) gradle任務(wù)集
任務(wù)的集合
tasks{
"opendoor"{
doFirst { println("打開(kāi)冰箱門(mén)") }
}
"putelephant"{
doFirst { println("放入大象") }
}.dependsOn("opendoor")
"closedoor"{
doFirst { println("關(guān)閉冰箱門(mén)") }
}.dependsOn("putelephant")
}
第7節(jié) 默認(rèn)屬性
gradle默認(rèn)自帶一些屬性,比如構(gòu)建路徑,配置文件等待,
打印gradle默認(rèn)配置信息
task("showConfig",{
//project:默認(rèn)工程,properties是工程屬性Map集合
project.properties.forEach { t, any ->
println("key="+t+",value="+any)
}
})
輸出結(jié)果:

第8節(jié) 默認(rèn)任務(wù)
控制臺(tái)輸入gradle執(zhí)行默認(rèn)任務(wù),不需要指定任務(wù)名稱(chēng)
task("showConfig",{
//project:默認(rèn)工程,properties是工程屬性Map集合
project.properties.forEach { t, any ->
println("key="+t+",value="+any)
}
})
//執(zhí)行默認(rèn)任務(wù)
defaultTasks("showConfig")
第9節(jié) 編寫(xiě)gradle增量式更新任務(wù)
增量式更新:哪個(gè)文件改變,才更新哪個(gè)
gradle增量式更新任務(wù)效率是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("")//清空數(shù)據(jù)
fileTree.forEach {
if(it.isFile){
//拼接,寫(xiě)入文件
Thread.sleep(1000)//為了演示增量更新效率
infoFile.appendText(it.absolutePath+"\r\n")
}
}
})
9.2 使用增量式更新
inputs.dir() //輸入目錄
inputs.file() //輸入文件
outputs.dir() //輸出目錄
outputs.file() //輸出文件
沒(méi)有變化,執(zhí)行0秒
plugins { java }
task("showSrcDir",{
//如果src目錄下內(nèi)容和info.txt沒(méi)有發(fā)生改變,任務(wù)不會(huì)執(zhí)行
inputs.dir("src") //輸入目錄
outputs.file("info.txt")//輸出文件
doFirst {
//獲取遍歷src目錄下的文件
val fileTree = fileTree("src")
val infoFile = file("info.txt")
infoFile.writeText("")//清空數(shù)據(jù)
fileTree.forEach {
if(it.isFile){
//拼接,寫(xiě)入文件
Thread.sleep(1000)
infoFile.appendText(it.absolutePath+"\r\n")
}
}
}
})
修改src目錄下Java源代碼,重新執(zhí)行,2秒鐘
public class Student {
//新增
private String name = "heima";
}
第10節(jié) gradle常見(jiàn)插件application,java
application插件:可以編寫(xiě)java工程、kotlin工程
java插件:只能編寫(xiě)java代碼
常用插件:https://docs.gradle.org/4.1/userguide/userguide.html
gradle所有插件:https://plugins.gradle.org/
//使用application插件
plugins { application }
//配置插件
application {
//設(shè)置主函數(shù)
mainClassName = "Girl"
}
第11節(jié) gradle依賴(lài)管理入門(mén)(普通程序員的開(kāi)發(fā)流程)
需求:使用http-client 3.1實(shí)現(xiàn)下載圖片功能
圖片路徑:http://img1.mm131.com/pic/946/1.jpg, …后面xxx/2.jpg依次類(lèi)推
普通程序員一般百度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
上面代碼運(yùn)行報(bào)錯(cuò)
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,下載添加到項(xiàng)目中
11.3 下載commons-codec.jar
上面代碼運(yùn)行報(bào)錯(cuò)
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
普通程序員百度,發(fā)現(xiàn)需要下載commons-codec.jar,然后下載添加到項(xiàng)目中
最終下載完成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節(jié) gradle依賴(lài)管理(高級(jí)程序員如何添加依賴(lài))
高級(jí)程序員使用依賴(lài)管理,不需要手動(dòng)下載jar包。
12.1 http-client maven倉(cāng)庫(kù)
百度:http-client 3.1 maven,找到http-client的maven倉(cāng)庫(kù),

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出現(xiàn)找不到主類(lèi)問(wèn)題的解決
我的Kotlin文件名:Downloader.kt
build.gradle.kts配置運(yùn)行主類(lèi):Downloader
運(yùn)行報(bào)錯(cuò):找不到或無(wú)法加載主類(lèi) Downloader
解決:運(yùn)行kotlin主類(lèi),需要在類(lèi)名后帶上Kt
application { mainClassName = "DownloaderKt"}
第13節(jié) gradle依賴(lài)管理的類(lèi)比
普通程序員百度查找解決方案,下載http-client.jar,錯(cuò)誤然后百度下載commons-logging.jar和commons-codec.jar,這種開(kāi)發(fā)效率很低,而且有個(gè)jar包可能依賴(lài)很多個(gè)jar包
高級(jí)程序員通過(guò)依賴(lài)管理,只需一個(gè)依賴(lài),其他相關(guān)commons-logging和commons-codec都會(huì)自定依賴(lài)到項(xiàng)目中,這就是gradle依賴(lài)管理的優(yōu)勢(shì)。

第14節(jié)
公共倉(cāng)庫(kù)和依賴(lài)配置階段
依賴(lài)管理:指在什么地方以什么形式引入外部代碼。
14.1 常用2個(gè)公共倉(cāng)庫(kù)
公共倉(cāng)庫(kù):
maven center:http://mvnrepository.com/
jcenter:https://bintray.com/bintray/jcenter
14.2 測(cè)試時(shí)依賴(lài)
依賴(lài)分為兩種:
編譯時(shí)依賴(lài):compile
測(cè)試時(shí)依賴(lài):testcompile,只在測(cè)試階段使用,項(xiàng)目打包上線(xiàn)不依賴(lài)。
build.gradle.kts添加測(cè)試依賴(lài)
maven倉(cāng)庫(kù):http://mvnrepository.com/artifact/junit/junit/4.12
…省略…
dependencies {
compile(kotlin("stdlib"))
//testCompile
group: 'junit', name: 'junit', version: '4.12'
//測(cè)試時(shí)依賴(lài)
testCompile("junit","junit","4.12")
}
repositories {
mavenCentral()
jcenter()
}
運(yùn)行結(jié)果:注意,測(cè)試類(lèi)代碼在src/main/test/java中,或者src/main/test/kotlin

第15節(jié) gradle依賴(lài)沖突的解決
15.1 什么是沖突
BOSS:我需要AB來(lái)幫我干活
A:我需要老王1.0版本來(lái)干活
B:我需要老王1.2版本來(lái)干活
BOSS:暈了
調(diào)用老王.開(kāi)發(fā)()的方法
究竟執(zhí)行的是老王1.0版本還是老王1.2版本干活呢?
15.2 gradle自動(dòng)依賴(lài)最高版本
第12節(jié)項(xiàng)目中,http-client依賴(lài)logging版本1.0.4,對(duì)該項(xiàng)目添加spring 4.3.9依賴(lài),發(fā)現(xiàn)loggin版本變成1.2

15.3 手動(dòng)解決依賴(lài)沖突
高版本logging1.2理論上兼容1.0.4版本,gradle會(huì)自動(dòng)解決版本兼容問(wèn)題,但是特殊情況,可能會(huì)出現(xiàn)沖突。
假如,我們希望保留http-client依賴(lài)的loggin 1.0.4版本,可以在compile spring依賴(lài)中添加閉包,讓spring去除loggin依賴(lài),運(yùn)行前面的下載美女圖片任務(wù),也沒(méi)有問(wèn)題
所以,以后遇到依賴(lài)沖突問(wèn)題。可以exclude取消其他項(xiàng)目依賴(lài),保留一個(gè)即可。

第16節(jié)
gradle插件自定義擴(kuò)展
16.1介紹
擴(kuò)展任務(wù):擴(kuò)展系統(tǒng)自帶的任務(wù),原來(lái)擴(kuò)展任務(wù)這么方便。
官方文檔:https://docs.gradle.org/current/dsl/index.html

16.2 擴(kuò)展copy任務(wù)
演示擴(kuò)展系統(tǒng)copy任務(wù)

文檔: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 擴(kuò)展delete任務(wù)
演示刪除src/main/temp目錄下文件
task("mydelete", Delete::class, {
setDelete("src/main/temp")
})
16.3 擴(kuò)展jar任務(wù)
演示把java文件打成jar包
task("myjar", Jar::class, {
//把src/main/java打成jar包到 myjar目錄
from("src/main/java")
archiveName = "myjar/a.jar"
})

第17節(jié) gradle調(diào)用外部擴(kuò)展
演示:Kotlin調(diào)用java代碼
為什么:以后開(kāi)發(fā),可能以前用Java寫(xiě)好了某些功能,現(xiàn)在直接使用Kotlin調(diào)用即可。
17.1 編譯java
點(diǎn)擊右側(cè)compileJava編譯Java文件成class

Java代碼
public class Girl {
public static void main(String[] args) {
System.out.println("我是美女");
}
}
17.2 kotlin任務(wù)調(diào)用Java
把上面編譯生成的Girl.class保存到項(xiàng)目根目錄
buid.gradle.kts代碼:
plugins { application }
task("callJava", {
javaexec {
//java主類(lèi)
main = "Girl"
//根目錄下
classpath(".")
}
})
運(yùn)行callJava任務(wù),輸出:我是美女。成功調(diào)用java代碼
第18節(jié) gradle的學(xué)習(xí)方法
如果大家仔細(xì)學(xué)會(huì)了上面的內(nèi)容, 基本上就成為國(guó)內(nèi)第一批 用kotlin語(yǔ)法編寫(xiě)gradle腳本的程序員.大家可以看到百度搜索只有16個(gè)相關(guān)文章,用kotlin編寫(xiě)gradle一定是以后的趨勢(shì), groovy這種動(dòng)態(tài)語(yǔ)言的語(yǔ)法,是有先天的不足的...

其實(shí)掌握學(xué)習(xí)方法比知識(shí)點(diǎn)重要:
1.保持技術(shù)敏感度、經(jīng)常關(guān)注gradle技術(shù)博客https://blog.gradle.org/,官方技術(shù)博客可以獲取第一手資料。
2.kotlin編寫(xiě)gradle示例代碼:https://github.com/gradle/kotlin-dsl/tree/master/samples#readme
3.CTO也是從普通開(kāi)發(fā)人員慢慢成長(zhǎng)而來(lái),CTO具備技術(shù)前瞻性,保持技術(shù)敏感度,日積月累。未來(lái),大家也能夠成長(zhǎng)為技術(shù)大牛。
文章比較長(zhǎng), 看起來(lái)比較累的話(huà)歡迎去看騰訊課堂的視頻, 大部分課程可以試學(xué),
如果您覺(jué)得內(nèi)容有幫助希望能購(gòu)買(mǎi)一下課程, 19.9元,每賣(mài)出一套我能分到2塊錢(qián), 就當(dāng)請(qǐng)我喝一瓶農(nóng)夫山泉吧. _
騰訊課堂教程配套視頻: https://ke.qq.com/course/235231