新一代構建工具gradle

Gradle是什么:

一個開源的項目自動化構建工具,建立在 Apache Ant 和 Apache Maven 概念的基礎上,并引入了基于 Groovy 的特定領域語言(DSL),而不是使用 XML 形式管理構建腳本。(構建工具:依賴管理、自動化運行測試、打包到指定位置)

目錄結構:

  • bin:Gradle的可執(zhí)行文件
  • init.d:初始化執(zhí)行腳本
  • lib:Gradle本身依賴的jar包
  • media:圖標文件

Groovy是什么

Groovy是用于Java虛擬機的一種敏捷的動態(tài)語言,它是一種成熟的面向?qū)ο缶幊陶Z言,既可以用于面向?qū)ο缶幊蹋挚梢杂米骷兇獾哪_本語言。使用該語言不必編寫過多的代碼,同時又具有閉包和動態(tài)語言中的其他特征。

與Java比較

  • Groovy完全兼容Java的語法
  • 分號是可選的
  • 類、方法默認是public的
  • 編譯器給屬性自動添加getter/setter方法
  • 屬性可以直接用點號獲取
  • 最后一個表達式的值會被作為返回值
  • ==等同于equals(),不會有NullPointerExceptions

高效的Groovy特性

  • assert語句,斷言操作
  • 可選類型定義
  • 可選的括號
  • 字符串
  • 集合API
  • 閉包

Groovy編程案例

public class ProjectVersion{
    private int major;
    private int minor      // 分號可選

    public ProjectVersion(int major, int minor){
        this.major = major
        this.minor = minor ;
    }

    public int getMajor(){
        major   // return可省
    }

    public int setMajor(int major){
        this.major = major ;
    }
}

ProjectVersion v1 = new ProjectVersion(1, 1) ;
println  v1.minor

ProjectVersion v2 = null ;

println v2 == v1 ;
// 1、可選的類型定義
def version = 1

// 2、assert
assert version == 2

// 3、括號是可選的
println(version)   // 可以寫成 println version

// 4、字符串
def s1 = 'imooc'
def s2 = "gradle version is ${version}"
def s3 = '''my name 
  is 
  imooc'''   // 支持換行

println s1
println s2
println s3

// 5、集合api
// list
def buildTools=['ant', 'maven']
buildTools << 'gradle'   // 追加一個元素
assert buildTools.getClass()  ==  ArrayList
assert buildTools.size()  == 3

// map
def buildYears = ['ant':2000, 'maven':2004]
buildYears.gradle = 2009
println buildYears.ant
println buildYears['gradle']
println buildYears.getClass()

// 6、閉包(代碼塊)
def c1 = {
    v ->
            print v
}

def c2 = {
    print 'hello'
}

def method1(Closure closure){
    closure('param')
}

def method2(Closure closure){
    closure()
}

method1(c1) ;
method2(c2) ;

groovy構建腳本

// 構建腳本中默認都是有個Project實例的,構建腳本中的代碼默認作用域都是Project
apply plugin: 'java'  // plugin: 'java'是命名參數(shù),apply 是Project實例上有一個方法,省略了括號

version = '0.1'  // Project實例有個屬性version

repositories {  // 一個閉包作為參數(shù)調(diào)用此方法
    mavenCentral()
}

dependencies {  // 同樣是一個閉包
    compile 'commons-codec : commons-codec : 1.6 '
}

Gradle工程目錄結構

Gradle目錄結構
group 'com.imooc.gradle'
version '1.0-SNAPSHOT'

apply plugin: 'java'  
apply plugin: 'war'  // 使用插件構建war包,注釋改行可構建jar包

sourceCompatibility = 1.8

repositories {
    mavenCentral()
}

dependencies {
    testCompile group: 'junit', name:'junit', version: '4.11'
}

構建腳本概要

構建塊

Gradle構建中的兩個基本概念是項目(project)和任務(task),每個構建至少包含一個項目,項目中包含一個或多個任務。在多項目構建中,一個項目可以依賴于其他項目;類似的,任務可以形成一個依賴關系圖來確保他們的執(zhí)行順序。

項目(project)

一個項目代表一個正在構建的組件(比如一個jar文件),當構建啟動后,Gradle會基于build.gradle實例化一個org.gradle.api.Project類,并且能夠通過project變量使其隱式可用。

  • 屬性:group、name、version(組件坐標)
  • 重要方法:apply(應用插件)、 dependencies(申明項目依賴的jar或其他項目)、repositories(去哪個倉庫獲取jar包)、task(申明項目里的人物)
  • 屬性的其他配置方式:ext(定義屬性)、gradle.properties(以鍵值對申明屬性)

任務(task)

任務對應org.gradle.api.Task。主要包括任務動作和任務依賴。任務動作定義了一個最小的工作單元??梢远x依賴于其他任務、動作序列和執(zhí)行條件。

  • dependsOn(申明任務依賴)
  • doFirst(task動作列表最前面添加動作)、doLast (簡寫方式:<<,動作列表末尾添加動作)

自定義任務

// 2、創(chuàng)建一個閉包,根據(jù)路徑創(chuàng)建文件
def createDir = {
    path  ->
            File dir = new File(path) ;
            if(!dir.exists()){
                 dir.mkdirs() ;
            }
}

// 1、自定義任務,自動創(chuàng)建目錄結構的功能
task makeJavaDir(){
    def paths = ['src/main/java', 'src/main/resources', 'src/test/java', 'src/test/resources'] ; 
    doFirst{
        paths.forEach(createDir) ;
    }
}

task makeWebDir(){
    dependsOn = 'makeJavaDir' ;  // 依賴
    doLast{
        paths.forEach(createDir) ;
    }
}
構建生命周期
  • 初始化:Gradle會根據(jù)構建腳本創(chuàng)造一個Project類,并且在這個腳本內(nèi)隱式可用。多項目構建中,初始化所有將要參與構建中的項目。
  • 配置:根據(jù)配置代碼(簡單說:除了動態(tài)代碼都是配置代碼),生成task依賴順序以及執(zhí)行順序。
  • 執(zhí)行階段:執(zhí)行動作代碼

依賴管理

幾乎所有的基于JVM的軟件項目都需要依賴外部類庫來重用現(xiàn)有的功能。自動化的依賴管理可以明確依賴的版本,可以解決因傳遞性依賴帶來的版本沖突。

工件坐標

  • group、name、version

常用倉庫

  • mavenLocal/mavenCentral/jcenter
    • mavenCentral/jcenter:公共倉庫
    • mavenLocal:本機使用過的jar的倉庫
  • 自定義maven倉庫
  • 文件倉庫(本地文件路徑作為倉庫:不建議使用)

依賴的傳遞性

  • B依賴A,如果C依賴B,那么C依賴A(造成版本沖突的原因)
自動化依賴管理

依賴管理的階段

依賴階段配置
  • compile、runtime(源代碼)
  • testCompile、testRuntime(測試代碼)
依賴階段關系
repositories { // 倉庫,依賴倉庫按順序進行依賴優(yōu)先級
    maven{   // 私服
        url '私服地址' 
    }
    mavenLocal()
    mavenCentral()
}

dependencies {
    compile 'ch.qos.logback:logback-classic:1.2.1'
    testCompile group: 'junit', name:'junit', version: '4.11'
}

依賴沖突

依賴沖突

解決沖突

  • 查看依賴報告

  • 排除傳遞性依賴

  • 強制一個版本

  • 修改默認解決策略(Gradle默認依賴最高版本來解決版本沖突)

    configurations.all{
      resolutionStrategy{
          failOnVersionConflict()   // 使構建失敗,可以知道哪些出現(xiàn)版本沖突
      }
    }
    
  • 排除傳遞性依賴

    compile('org.hibernate:hibernate-core:3.6.3.Final'){
      exclude group:"org.slf4j", module:"slf4j-api" // transitive=false
    }
    
  • 強制指定一個版本

    configurations.all{
      resolutionStrategy{
          force  'org.slf4j:slf4j-api:1.7.24'
      }
    }
    

    項目模塊化

    在企業(yè)項目中,包層次和類關系比較復雜,把代碼拆分成模塊通常是最佳實踐,這需要你清晰的劃分功能的邊界,比如把業(yè)務邏輯和數(shù)據(jù)持久化拆分開來。項目符合高內(nèi)聚低耦合時,模塊化就變得很容易,這是一條非常好的軟件開發(fā)實踐。

模塊依賴關系

配置要求

  • 所有項目應用Java插件
  • web子項目打包成WAR
  • 所有項目添加logback日志功能
  • 統(tǒng)一配置公共屬性


    項目范圍

settings.gradle:管理多項目構建

rootProject.name = 'todo'   // 根項目
include 'repository'  // 子項目
include 'model'
include 'web'

web項目:

dependencies {
    compile project(":repository")
    testCompile group: 'junit', name:'junit', version: '4.11'
}

todo項目:

allprojects{   // 全局配置
    apply plugin: 'java'
    sourceCompatibility = 1.8
}

// 所有項目添加logback日志功能
subprojects{
    repositories{
        mavenCentral()
    }
    dependencies{
         compile 'ch.qos.logback:logback-classic:1.2.1'
         testCompile group: 'junit', name:'junit', version: '4.11'
    }
}

統(tǒng)一配置group和version

根項目添加:gradle.properties文件

group = 'com.imooc.gradle'
version = 1.0-SNAPSHOT

自動化測試

一些開源的測試框架,比如JUnit,TestNG能夠幫助你編寫可復用的結構化的測試,為了運行這些測試,你要先編譯它們,就像編譯源代碼一樣。測試代碼的作用僅僅用于測試的情況,不應該被發(fā)布到生產(chǎn)環(huán)境中,需要把源代碼和測試代碼分開來。

項目布局

項目布局

測試配置

dependencies{
    testCompile  'junit:junit:4.11'
}

測試發(fā)現(xiàn)

  • 任何繼承自junit.framework.TestCase或groovy.util.GroovyTestCase的類
  • 任何被@RunWith注解的類
  • 任何至少包含一個被@Test注解的類

發(fā)布到本地倉庫和遠程倉庫

allprojects{ 
    apply plugin: 'java'
    sourceCompatibility = 1.8

    apply plugin:  'maven-public'

    publishing{
        publications{
            myPublish(MavenPublication){  // 自定義函數(shù)
               from components.java 
           }
        }
        repositories{
            maven{
                name  "myRepo"  // 自定義倉庫名
                url  ""  // 自己倉庫
            }
        }
    }
}
最后編輯于
?著作權歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內(nèi)容