Gradle自動化項目構建之快速掌握Groovy

Groovy介紹

  1. 是一種基於JVM的敏捷開發語言
  2. 結合了Python、Ruby、Smalltalk的許多強大特性
  3. Groovy能夠與Java完美結合,並且可使用Java全部的庫

Groovy特性

  1. 語法上支持動態類型,閉包等新一代語言特性
  2. 無縫集成全部已存在的Java類庫
  3. 即支持面向對象編程也支持面向過程編程

Groovy優點

  1. 一種更加敏捷的編程語言
  2. 入門很是容易,但功能很是強大
  3. 便可以做爲編程語言也能夠做爲腳本語言
  4. 熟悉Java會很是容易掌握Groovy

Groovy基礎語法

1. Groovy中語句結束符可使用「;」,也能夠不使用;

2. Groovy中類、變量和方法,默認是public。

3. 輸出語句

// 1. 能夠和Java同樣
class HelloWorld {
    public static void main(String[] args) {
        System.out.println("Hello Groovy")
    }
}

// 2. 直接輸出(兩種)
println "Hello Groovy"
println("Hello Groovy")
複製代碼

4. Groovy中的變量

  1. 變量的類型:基本類型(java中的int/float/double/byte/char/long/short)和對象類型(String等) ,在Groovy中最終都是對象類型。java

    int x = 10
    println x.class //結果爲:class java.lang.Integer
    
    double y = 3.14
    println y.class //結果爲:class java.lang.Double
    複製代碼

    因而可知,Groovy中的基本類型最終會被編譯器包裝成對象類型python

  2. 變量的定義:強類型定義方式和弱類型def定義方式android

    def x1 = 10
    def y1 = 3.14
    def str1 = 'groovy str'
    x1 = 'grovvy def'
    
    println x1.class //class java.lang.Integer
    println y1.class //class java.math.BigDecimal
    println str1.class //class java.lang.String
    println x1.class //class java.lang.String
    複製代碼

    強類型定義及定義的時候寫明變量的類型,而def則由編譯器自行推導變量的類型編程

    強類型定義方式和弱類型def定義方式的選擇:json

    * 變量用於本類或者本模塊而不會用於其它類或者其餘模塊,推薦使用def類型,這樣能夠隨時動態的轉換爲其它類型;
     * 變量要用於其它類或是其它模塊,強烈建議使用強類型定義方式。使用強類型定義的方式不能動態轉換類型,才能使外界傳入或者調用的時候不會對於數據的類型產生疑惑,這樣就保證外界傳入的數據必定是咱們想要的正確的類型的數據。
    複製代碼

5. 字符串詳解

  1. 兩種字符串:String(同Java中的String同樣)、GString
  2. 字符串經常使用的三種定義方式
    //1. 單引號定義的就是java中的String,內容即爲''內的字符串,而且不可更改
    def str1 = 'a single string'
    println str1.class  //class java.lang.String
    // 有特殊字符一樣的經過反斜槓轉義
    def str2 = 'a single \'special\' string'
    
    //2. 三個單引號定義的是有格式的字符串,會直接按照咱們寫的格式進行輸出,而不用像Java中進行拼接
    def trebleStr = '''line one line two line three '''
        
    //3. 雙引號
    def name = "Groovy"
    println name.class  //class java.lang.String
    // 字符串模板
    def sayHello = "Hello $name"
    // 字符串模板也能夠是表達式
    def sum = "the sum of 2 and 3 equals ${2 + 3}"
    複製代碼
  3. String方法來源
    • java.lang.String原有的方法
    • DefaultGroovyMethods:是Groovy對全部對象的一個擴展
    • StringGroovyMethods:繼承自DefaultGroovyMethods,重寫了DefaultGroovyMethods中的許多方法,使這些方法更加適用於String使用。
  4. Groovy中的兩種字符串,對於開發者都是字符串,和以前正常定義便可。二者之間的轉換都是編譯器完成的,開發者不關注這些。即使定義的是Java的String,可使用GString的方法,最終的轉換都是編譯器完成。所以,String 和GString之間能夠相互調用和傳遞,不須要考慮它們之間的轉換問題。
  5. 字符串方法
    //字符串填充:
    // 1. center(Number numberOfChars,CharSequence padding) ,將字符串做爲中心進行填充
    // 當numberOfChars小於或等於str自己的長度時,不進行填充操做,大於則用pandding擴展至長度numberOfChars,從字符串的右邊(尾)進行填充,再到左邊(頭)
    def str = "groovy"
    println str.center(8)     //結果: groovy ,不傳padding表明以空格填充
    println str.center(5,"a") //結果: groovy
    println str.center(6,"a") //結果:groovy
    println str.center(7,"a") //結果:groovya
    println str.center(8,"a") //結果:agroovya
    println str.center(9,"a") //結果:agroovyaa
    // 2. padLeft(Number numberOfChars,CharSequence padding) ,在字符串的左邊進行填充
    // 3. padRight(Number numberOfChars,CharSequence padding),在字符串的右邊進行填充
        
    //字符串比較:
    def string = "groovy"
    def string1 = "Groovy"
    println string.compareTo(string1)             // 32     結果大於0,str大於Str2
    println string.compareToIgnoreCase(string1)   // 0      結果等於0,str等於忽略大小寫的Str
    println string1.compareTo(str)                // -32    結果小於0,str2小於str
    println string > string1                      // true   可用操做符直接進行比較
    println string == string1.toLowerCase()       // true
        
    //獲取字符串中的字符:
    def string2 = "groovy"
    println string2.getAt(0) // g
    println string2.getAt(0..1)     // gr
    println string2[0]              // g
    println string2[0..1]           // gr
        
    //字符串中的減法(取差集):
    def string3 = "groovy"
    def string4 = "hello"
    def string5 = "hello groovy"
    def string6 = "groovy hello "
    
    println string3.minus(string4) // groovy,       str中沒有包含str2
    println string3.minus(string5) // groovy,       str中沒有包含str3
    println string5.minus(string4) // groovy,       str3中包含了str2 (注意結果包含了空格)
    println string5.minus(string6) // hello groovy, str3z中沒有包含str4
    println string5 - string3      // hello,        str3z中包含了str(注意結果包含了空格)
    
    // 其它方法
    def string7 = "hello groovy"
    println string7.reverse() // yvoorg olleh,字符串反轉
    println string7.capitalize()// Hello groovy,首字母大寫
    println string7.isNumber() // false,是否全是數字
    def string8 = "1234"
    println string8.toInteger() // 1234
    println string8.toBigDecimal() // 1234
    println string8.toDouble() // 1234.0
    複製代碼

6. 邏輯控制

  1. if/else:同Java
  2. switch/case:Java中switch只能傳入int類型、byte,char和short類型能自動提高爲int類型、String類型和後來擴展的enum類型。而在Groovy中,switch能夠傳入任性類型的數據進行匹配。
    String judgeType(Object x) {
        def result
        switch (x) {
            case "string":
                result = "x is string"
                break
            case [4, 5, 6, 7,'inList']: //列表(數據結構中講解)
                result = "x is in list [4, 5, 6, 7,'inList']"
                break
            case 10..15: //範圍range(數據結構中講解)
                result = "x is in range 10..15"
                break
            case Integer:
                result = "x is Integer"
                break
            case BigDecimal:
                result = "x is BigDecimal"
                break
            case List:
                result = "x is List"
                break
            default:
                result = "no match"
                break
        }
        return result
    }
    複製代碼

7. 循環邏輯

  1. while循環:同Java
  2. for循環
    // 1. 範圍中的for循環
    def sum = 0
    for (i in 0..9) {
        sum += i
    }
    println sum // 45
    
    sum = 0
    // 2. list中的for循環
    for (i in [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]) {
        sum += i
    }
    println sum // 45
    
    // 3. map中的for循環
    for (i in ['java': 1, ' groovy': 2, 'python': 3]) {
        println "key:${i.key} value:${i.value}"
    }
    複製代碼

8. 閉包

  1. 定義:Groovy中的閉包是一個開放的,匿名的代碼塊,能夠接受參數,能夠返回值而且能夠賦值給閉包變量。閉包能夠引用在其周圍範圍內聲明的變量,與閉包的正式定義相反,Groovy語言中的Closure也能夠包含在其周圍範圍以外定義的自由變量。api

  2. 語法:{ [closureParameters -> ] statements } 。其中[closureParameters->]是一個以逗號分隔的可選參數列表,並且statements 有0條或更多條Groovy語句,參數看起來相似於方法參數列表,這些參數能夠是類型化的或非類型化的。指定參數列表時, - >字符是必需的,用於將參數列表與Groovy語句分開。數組

  3. 代碼示例bash

    { item++ }          //一個引用名爲item的變量的閉包          
    
    { -> item++ }       //經過添加箭頭( - >)能夠明確地將閉包參數與代碼分開         
    
    { println it }      //使用隱式參數(it)的閉包    
    
    { it -> println it }    //上面的一個替代版本,它是一個顯式參數         
    
    { name -> println name }    //在這種狀況下,一般最好爲參數使用顯式名稱        
    
    { String x, int y ->        //一個閉包接受兩個類型參數         
        println "hey ${x} the value is ${y}"
    }
    
            { reader ->                 //閉包能夠包含多個語句         
                def line = reader.readLine()
                line.trim()
            }
    
    // 上面代碼定義一個名爲 closure_name 的閉包,用途由 closure body 中的代碼定義。
    // 匿名閉包指不聲明閉包變量名,只有閉包方法體{ //closure body }
    def closure_name = {
        // closure body
    }
    複製代碼
  4. 閉包類:一個閉包是groovy.lang.Closure類的一個實例,它能夠像任何其餘變量同樣賦值給變量或字段,儘管它是一個代碼塊。Java8中lambda表達式也引入了閉包概念,類com.sun.corba.se.spi.orbutil.closure.Closure。Groovy將閉包定義爲Closure類的實例,與Java 8中的lambda表達式大相徑庭。數據結構

  5. 參數閉包

    1. 普通參數:閉包的參數和常規方法的參數同樣,遵循相同的原則。
    2. 隱式參數:當閉包沒有顯式定義參數列表(使用 - >定義)時,閉包老是定義一個名爲it的隱式參數。
    3. 可變參數:閉包能夠像任何其餘方法同樣聲明可變參數。可變參數方法的特色是:參數的數量是可變的。有2種狀況:最後一個參數是可變長度的參數,或者是一個數組參數。
  6. 閉包調用:def closure_name = { // closure body }

    1. closure_name.call()
    2. closure_name()
  7. 閉包使用:閉包能夠用做方法的參數。在Groovy中,不少用於數據類型(例如列表和集合)的內置方法都有閉包做爲參數類型。

    def clos = { param -> println "${str1} ${param}" }
    clos("Groovy")
    clos.call("World");
    // 閉包和列表
    def lst = [11, 12, 13, 14];
    lst.each {println it}
    // 閉包和映射
    def mp = ["TopicName" : "Maps", "TopicDescription" : "Methods in Maps"]
    mp.each {println it}
    mp.each {println "${it.key} maps to: ${it.value}"}
    複製代碼
  8. 閉包進階

    1. 閉包三個重要變量:this,owner,delegate
      // '注:此段代碼位於HelloWorld.groovy文件中'
      
      // '1. 直接在閉包中使用時: 三者沒有區別'
      def scriptClosure = {
          println "scriptClosure this:" + this // 表明閉包定義處的類
          println "scriptClosure owner:" + owner // 表明閉包定義處的類或對象(靜態是class文件,非靜態是對象)
          println "scriptClosure delegate:" + delegate // 表明任意對象,默認與owner一致
      }
      // 輸出結果:
      scriptClosure  this:main.HelloWorld@6ce139a4
      scriptClosure  owner:main.HelloWorld@6ce139a4
      scriptClosure  delegate:main.HelloWorld@6ce139a4
      
      // '2. 閉包內部的閉包,this與 owner和delegate是不一樣的'
      /**
       * 1. 在類或者閉包中定義的閉包,三者沒有區別
       * 2. 在閉包中定義的閉包 this 與 owner ,delegate就不同了
       * 3. this :永遠會指向最外層的類
       * 4. owner和delegate默認都會指向定義出最近的closure對象
       */
      def nestClosure = {
          def innerClosure = {
              println "innerClosure this:" + this
              println "innerClosure owner:" + owner
              println "innerClosure delegate:" + delegate
          }
          innerClosure.call()
      }
      nestClosure.call()
      // 輸出結果:
      innerClosure  this:main.HelloWorld@6ce139a4
      innerClosure  owner:main.HelloWorld$_run_closure6@33afa13b
      innerClosure  delegate:main.HelloWorld$_run_closure6@33afa13b
      
      // '3. 修改delegate指向的對象'
      def nestClosure = {
          def innerClosure = {
              println "innerClosure this:" + this
              println "innerClosure owner:" + owner
              println "innerClosure delegate:" + delegate
          }
          innerClosure.delegate = new HelloWorld()
          innerClosure.call()
      }
      nestClosure.call()
      // 輸出結果:
      innerClosure  this:main.HelloWorld@6ce139a4
      innerClosure  owner:main.HelloWorld$_run_closure6@45b9a632
      innerClosure  delegate:main.HelloWorld@25d250c6
      複製代碼
      • 在大多數狀況下 this,owner,delegate的值是同樣的
      • 在閉包中定義閉包的時候,this與 owner,delegate就不同了
      • 在修改了delegate 的值得時候 owner 和 delegate 就不同了
      • this 與 owner 只要定義了就不能夠修改,delegate 能夠更改
      • this永遠是指定義該閉包類,若是存在內部類,則是最內層的類,但this不是指當前閉包對象
      • owner永遠是指定義該閉包的類或者閉包,顧名思義,閉包只能定義在類中或者閉包中
    2. 閉包的委託策略
      // '1. 正常調用'
      class Student {
          String name
          def pretty = { println "My name is ${name}" }
      
          String toString() {
              pretty.call()
          }
      }
      
      class Teather {
          String name
      }
      
      def student = new Student(name: "groovy")
      def teather = new Teather(name: "android")
      student.toString()
      // 結果:My name is groovy
      // 緣由:每一個閉包都會有本身的委託策略,默認的委託策略是 Closure.OWNER_FIRST(所以這也是爲何大多數狀況和owner一致的緣由)
      
      // 2. '更改委託策略委託'
      student.pretty.delegate = teather
      // 更改對應的委託策略委託才真正生效
      student.pretty.resolveStrategy = Closure.DELEGATE_FIRST
      student.toString()
      // 結果:My name is android
      複製代碼
      • Closure.OWNER_FIRST是默認策略。優先在owner尋找,owner沒有再delegate
      • Closure.DELEGATE_FIRST:優先在delegate尋找,delegate沒有再owner
      • Closure.OWNER_ONLY:只在owner中尋找
      • Closure.DELEGATE_ONLY:只在delegate中尋找
      • Closure.TO_SELF:高級選項,讓開發者自定義策略。
  9. 閉包代碼塊中,只要是this、owner、delegate三者中擁有的屬性和方法,閉包中都是能夠直接(可省略引用)調用到的。區別在於存在一個執行順序,執行順序是閉包的委託策略決定。

    // rootProject : build.gradle
    buildscript { ScriptHandler scriptHandler ->
        // 配置工程倉庫地址
        scriptHandler.repositories { RepositoryHandler repositoryHandler ->
            repositoryHandler.jcenter()
            repositoryHandler.mavenCentral()
            repositoryHandler.mavenLocal()
            repositoryHandler.ivy {}
            repositoryHandler.maven { MavenArtifactRepository mavenArtifactRepository ->
                mavenArtifactRepository.name 'personal'
                mavenArtifactRepository.url 'http://localhost:8081/nexus/repositories/'
                mavenArtifactRepository.credentials {
                    username = 'admin'
                    password = 'admin123'
                }
            }
        }
    }
    
    // ======================== 上述簡化後 =============================
    
    buildscript {
        /**
         * 配置工程倉庫地址
         *  因爲repositories這個閉包中的delegate是repositoryHandler,
         *      所以能夠省略repositoryHandler的引用,直接使用其屬性和方法。
         */
        repositories {
            jcenter()
            mavenCentral()
            mavenLocal()
            ivy {}
            maven {
                name 'personal'
                url 'http://localhost:8081/nexus/repositories/'
                credentials {
                    username = 'admin'
                    password = 'admin123'
                }
            }
        }
    }
    複製代碼

9. 範圍

  1. 定義:範圍是指定值序列的速記。範圍由序列中的第一個和最後一個值表示,Range能夠是包含或排除。包含範圍包括從第一個到最後一個的全部值,而獨佔範圍包括除最後一個以外的全部值。
  2. 使用示例:
    1..10 - 包含範圍的示例
    1 .. <10 - 獨佔範圍的示例
    'a'..'x' - 範圍也能夠由字符組成
    10..1 - 範圍也能夠按降序排列
    'x'..'a' - 範圍也能夠由字符組成並按降序排列。
    def range = 1..10
    複製代碼
  3. 經常使用方法:
    contains()      檢查範圍是否包含特定值
    get()           返回此範圍中指定位置處的元素。
    getFrom()       得到此範圍的下限值。
    getTo()         得到此範圍的上限值。
    isReverse()     這是一個反向的範圍,反向迭代
    size()          返回此範圍的元素數。
    subList()       返回此指定的fromIndex(包括)和toIndex(排除)之間的此範圍部分的視圖
    複製代碼

10. 列表

  1. 定義:列表是用於存儲數據項集合的結構。在Groovy中,List保存了一系列對象引用。List中的對象引用佔據序列中的位置,並經過整數索引來區分。列表文字表示爲一系列用逗號分隔並用方括號括起來的對象。要處理列表中的數據,咱們必須可以訪問各個元素。Groovy列表使用索引操做符[]索引。列表索引從零開始,這指的是第一個元素。
  2. 使用示例:
    [11,12,13,14] - 整數值列表
    ['Angular''Groovy''Java'] - 字符串列表
    [1,2,[3,4],5] - 嵌套列表
    ['Groovy',21,2.11] - 異構的對象引用列表
    [] - 一個空列表
    def arrayList = [1, 2, 3, 4]
    複製代碼
  3. 經常使用方法
    add()           將新值附加到此列表的末尾。
    contains()      若是此列表包含指定的值,則返回true。
    get()           返回此列表中指定位置的元素。
    isEmpty()       若是此列表不包含元素,則返回true
    minus()         建立一個由原始元素組成的新列表,而不是集合中指定的元素。
    plus()          建立由原始元素和集合中指定的元素組成的新列表。
    pop()           今後列表中刪除最後一個項目
    remove()        刪除此列表中指定位置的元素。
    reverse()       建立與原始列表的元素相反的新列表
    size()          獲取此列表中的元素數。
    sort()          返回原始列表的排序副本。
    複製代碼

11. 映射

  1. 定義:映射(也稱爲關聯數組,字典,表和散列)是對象引用的無序集合。Map集合中的元素由鍵值訪問。 Map中使用的鍵能夠是任何類。當咱們插入到Map集合中時,須要兩個值:鍵和值。
  2. 使用示例:
    ['TopicName''Lists''TopicName''Maps'] - 具備TopicName做爲鍵的鍵值對的集合及其相應的值。
    [:] - 空映射。
    def map = ['key': 'value']
    複製代碼
  3. 經常使用方法
    containsKey()   此映射是否包含此鍵?
    get()           查找此Map中的鍵並返回相應的值。若是此映射中沒有鍵的條目,則返回null。
    keySet()        獲取此映射中的一組鍵。
    put()           將指定的值與此映射中的指定鍵相關聯。若是此映射先前包含此鍵的映射,則舊值將替換爲指定的值。
    size()          返回此地圖中的鍵值映射的數量。
    values()        返回此地圖中包含的值的集合視圖。
    複製代碼

12. 面向對象:

  1. Groovy中類的特色
    1. Groovy中的類默認都是public類型的,全部的方法變量默認都是public類型的
    2. Groovy中的類默認集成自GroovyObject ,在這個類中默認實現了getProperty和 setProperty方法。
    3. Groovy中在建立對象的同時能夠對變量進行賦值,能夠選擇對部分或者所有進行賦值
    4. Groovy中不管是直接.變量,仍是調用get/set方法獲取或者設置變量,最終調用的都是get/set。
    class HelloGroovy {
        String name
        Integer age
            
        // def等同於Java中的Object
        def invokeMethod(String method, Object args){
            return "invokeMethod : the method is ${method},the args is ${args}"
        }
        
        static void main(String[] args) {
            //賦值: 能夠不初始化,也能夠初始化部分或者所有
            def hello = new HelloGroovy(name: "dog",age: 2)
            //hello.name的方式獲取變量的值,其實最終的實現也是 animal.getName()
            println "this animal's name is ${hello.name},the animal's age is ${hello.age}"
            }
        }
    複製代碼
  2. Groovy中接口的特色:接口中不準定義非public的方法
  3. trait:Groovy中獨有的面向對象的語法特性,Trait能夠被看做是具備方法實現和狀態的接口。它的使用方法和接口同樣,都是使用implements關鍵字,這個看上去感受跟繼承有點相似,但又不同,trait僅僅是將其方法和狀態嵌入到實現類中,而沒有繼承中的那種上下級的父子關係。
    1. trait中支持定義抽象方法,其實現類必須實現此抽象方法。
    2. trait中能夠定義私有方法,其實現類沒法訪問。
    3. trait中的this關鍵字指其實現類。
    4. trait能夠實現接口。
    5. trait中可定義屬性,此屬性會自動被附加到實現此trait的類中。
    6. trait可定義私有字段因爲存儲相關狀態。
    7. trait可定義公共字段,但爲了不鑽石問題,其獲取方式有所不一樣
  4. Groovy中方法調用的特色:編碼階段,若一個方法不存在時,Groovy並不會報錯。而在執行過程當中時,若不存在某方法,則首先會找當前類是否重寫了methodMissing方法,若重寫則調用,若methodMissing方法沒有重寫,則會查找當前類是否重寫了invokeMethod方法,若重寫了則調用,不然就會報錯。
    class HelloGroovy {
    
        /**
        *  一個方法在找不到時,調用這個方法做爲代替
        *  優先於 invokeMethod()
        */
        def methodMissing(String method, Object args) {
            return "methodMissing : the method is ${method},the args is ${args}"
        }
    
        // 一個方法在找不到時,調用這個方法做爲代替
        def invokeMethod(String method,Object args){
            return "invokeMethod : the method is ${method},the args is ${args}"
        }
    
        static void main(String[] args) {
            def hello = new HelloGroovy()
            //調用不存在的方法
            hello.call()
        }
    }
    複製代碼
  5. Groovy中的元編程:
    1. 使用metaClass() 方法動態的爲對象插入屬性
    2. 使用metaClass() 方法動態的爲對象插入方法
    3. 使用metaClass() 方法動態的爲對象插入靜態方法
    4. 應用功能場景:當咱們引用第三方的框架時,很容易引用的到沒法修改的jar文件和final修飾的類,這個時候咱們沒法修改類的屬性,可咱們又特別的但願能夠插入一個變量或者插入或修個一個方法,好比破解,這時候若是有了動態注入變量或者是方法,咱們就能夠輕鬆實現咱們的需求了。固然咱們這樣動態注入的變量和方法是不能在真的應用中被使用的,有必定的做用域的限制(只能在當前頁面使用)。
    class HelloGroovy {
        String name
        Integer version
    
        static void main(String[] args) {
            // 元編程爲類動態注入屬性
            HelloGroovy.metaClass.desc = "我是描述信息"
            def groovy = new HelloGroovy()
            groovy.desc = "我是Groovy"
            println(groovy.desc)
    
            // 元編程爲類動態注入方法
            HelloGroovy.metaClass.descUpcase = {
                it -> it.toUpperCase()
            }
            HelloGroovy.metaClass.english = "I am Groovy"
            def helloGroovy = new HelloGroovy()
            println helloGroovy.descUpcase(helloGroovy.english)
    
            // 元編程爲類動態注入靜態方法
            HelloGroovy.metaClass.static.addVersion = {
                it -> it + 1
            }
            HelloGroovy.metaClass.desc = "注入靜態方法"
            def staticInject = new HelloGroovy(name: "groovy", version: 2)
            println "the language's name is ${staticInject.name}, the language's next version is ${staticInject.addVersion(staticInject.version)}"
        }
    }
    
    // 輸出結果:
    我是Groovy
    I AM GROOVY
    the language's name is groovy, the language's next version is 3
    複製代碼

13. 異常處理:相似Java

Groovy的高級語法

1. Json操做

  1. JsonSlurper:JsonSlurper是一個將JSON文本或閱讀器內容解析爲Groovy數據的類結構,例如地圖,列表和原始類型,如整數,雙精度,布爾和字符串。
  2. JsonOutput: 此方法負責將Groovy對象序列化爲JSON字符串。
//Json解析:JSON文本或閱讀器內容解析爲Groovy數據結構的類
def jsonSlurper = new JsonSlurper()
// 文本解析
def object = jsonSlurper.parseText('{ "name": "John", "ID" : "1"}')
println(object.name);
println(object.ID);
// 解析整數列表
Object listObj = jsonSlurper.parseText('{ "List": [2, 3, 4, 5] }')
listObj.each { println it }
// 解析基本數據類型列表
def obj = jsonSlurper.parseText ''' {"Integer": 12, "fraction": 12.55, "double": 12e13}'''
println(obj.Integer);
println(obj.fraction);
println(obj.double);
    
//Json序列化:將Groovy對象序列化爲JSON字符串
def output = JsonOutput.toJson([name: 'John', ID: 1])
println(output)
class Student{
    String name
    Integer ID
}
def output1 = JsonOutput.toJson([new Student(name: 'John',ID:1), new Student(name: 'Mark',ID:2)])
println(output1);
複製代碼

2. XML操做

  1. XML標記構建器:Groovy支持基於樹的標記生成器BuilderSupport,它能夠被子類化以生成各類樹結構對象表示。一般,這些構建器用於表示XML標記,HTML標記。 Groovy的標記生成器捕獲對僞方法的調用,並將它們轉換爲樹結構的元素或節點。這些僞方法的參數被視爲節點的屬性。做爲方法調用一部分的閉包被視爲生成的樹節點的嵌套子內容。
  2. XML解析器:Groovy XmlParser類使用一個簡單的模型來將XML文檔解析爲Node實例的樹。每一個節點都有XML元素的名稱,元素的屬性和對任何子節點的引用。這個模型足夠用於大多數簡單的XML處理。
//XML解析
def stringXml = ''' <collection shelf = "New Arrivals"> <movie title = "Enemy Behind"> <type>War, Thriller</type> <format>DVD</format> <year>2003</year> <rating>PG</rating> <stars>10</stars> <description>Talk about a US-Japan war</description> </movie> <movie title = "Transformers"> <type>Anime, Science Fiction</type> <format>DVD</format> <year>1989</year> <rating>R</rating> <stars>8</stars> <description>A schientific fiction</description> </movie> <movie title = "Ishtar"> <type>Comedy</type> <format>VHS</format> <year>1987</year> <rating>PG</rating> <stars>2</stars> <description>Viewable boredom </description> </movie> </collection> '''
def parser = new XmlParser()
// 解析文本
def text = parser.parseText(stringXml)
println text.movie[0].type[0].text()
// 解析文件
def doc = parser.parse("E:\\CodeProject\\groovy\\HelloWorld\\src\\main\\Movies.xml")
println doc
// 輸出結果:
War, Thriller
collection[attributes={shelf=New Arrivals}; value=[movie[attributes={title=Enemy Behind}; value=[type[attributes={}; value=[War, Thriller]], format[attributes={}; value=[DVD]], year[attributes={}; value=[2003]], rating[attributes={}; value=[PG]], stars[attributes={}; value=[10]], description[attributes={}; value=[Talk about a US-Japan war]]]], movie[attributes={title=Transformers}; value=[type[attributes={}; value=[Anime, Science Fiction]], format[attributes={}; value=[DVD]], year[attributes={}; value=[1989]], rating[attributes={}; value=[R]], stars[attributes={}; value=[8]], description[attributes={}; value=[A schientific fiction]]]], movie[attributes={title=Ishtar}; value=[type[attributes={}; value=[Comedy]], format[attributes={}; value=[VHS]], year[attributes={}; value=[1987]], rating[attributes={}; value=[PG]], stars[attributes={}; value=[2]], description[attributes={}; value=[Viewable boredom]]]]]]
// 解析節點遍歷
doc.movie.each{
    bk->
        print("Movie Name:")
        println "${bk['@title']}"

        print("Movie Type:")
        println "${bk.type[0].text()}"

        print("Movie Format:")
        println "${bk.format[0].text()}"

        print("Movie year:")
        println "${bk.year[0].text()}"

        print("Movie rating:")
        println "${bk.rating[0].text()}"

        print("Movie stars:")
        println "${bk.stars[0].text()}"

        print("Movie description:")
        println "${bk.description[0].text()}"
        println("*******************************")
}

//XML標記生成器
def mB = new MarkupBuilder()
// 根節點是誰,調用的方法就是誰
mB.collection(shelf : 'New Arrivals') {
    movie(title : 'Enemy Behind')
    type('War, Thriller')
    format('DVD')
    year('2003')
    rating('PG')
    stars(10)
    description('Talk about a US-Japan war')
}
// 注1:mB.collection() -這是一個標記生成器,用於建立<collection> </ collection>的頭XML標籤
// 注2:movie(title : 'Enemy Behind') -這些僞方法使用此方法建立帶有值的標記的子標記。經過指定一個名爲title的值,這實際上表示須要爲該元素建立一個屬性。
// 注3:向僞方法提供閉包以建立XML文檔的剩餘元素。

// 根據map生成XML
def mapXml = [1 : ['Enemy Behind', 'War, Thriller','DVD','2003',
                   'PG', '10','Talk about a US-Japan war'],
              2 : ['Transformers','Anime, Science Fiction','DVD','1989',
                   'R', '8','A scientific fiction'],
              3 : ['Trigun','Anime, Action','DVD','1986',
                   'PG', '10','Vash the Stam pede'],
              4 : ['Ishtar','Comedy','VHS','1987', 'PG',
                   '2','Viewable boredom ']]
// Compose the builder
def MOVIEDB = mB.collection('shelf': 'New Arrivals') {
    mapXml.each {
        sd ->
            mB.movie('title': sd.value[0]) {
                type(sd.value[1])
                format(sd.value[2])
                year(sd.value[3])
                rating(sd.value[4])
                stars(sd.value[4])
                description(sd.value[5])
            }
    }
}
println MOVIEDB
複製代碼

3. 文件IO操做(Groovy在使用IO時提供了許多輔助方法,並提供了更簡單的類操做文件)

  1. 讀取文件
  2. 寫入文件
  3. 遍歷文件樹
  4. 讀取和寫入數據對象到文件
  5. Groovy的文件方法會本身幫助咱們關閉流,不須要咱們關心
// 讀取文件
def file = new File('src/main/Movies.xml')
file.eachLine {
    line -> println "line : $line";
}
// 讀取文件的內容到字符串
println file.text
// 讀取文件部份內容
def reader = file.withReader {
    char[] buff = new char[100]
    it.read(buff)
    return buff
}
println reader

// 寫入文件
new File('E:\\CodeProject\\groovy\\HelloWorld','Example.txt').withWriter('utf-8') {
    writer -> writer.writeLine 'Hello World'
}

// 獲取文件的大小
println file.length()

// 測試文件是不是目錄
println "File? ${file.isFile()}"
println "Directory? ${file.isDirectory()}"

// 建立目錄
def fileMkDir = new File('E:\\CodeProject\\groovy\\HelloWorld\\IO')
fileMkDir.mkdir()

// 刪除文件
fileMkDir.delete()

// 複製文件
def src = new File("E:\\CodeProject\\groovy\\HelloWorld\\Example.txt")
def dst = new File("E:\\CodeProject\\groovy\\HelloWorld\\Example1.txt")
dst << src.text

// 獲取目錄內容
def rootFiles = file.listRoots()
rootFiles.each {
    println it.absolutePath
}

// 對象存儲,寫入文件
def saveObject(Object o, String path) {
    //判斷目標文件不存在,建立文件
    File destFile = new File(path)
    try {
        if (!destFile.exists()) {
            destFile.createNewFile()
        }
    } catch (Exception e) {
        e.printStackTrace()
    }
    if (o == null) {
        return
    }
    try {
        destFile.withObjectOutputStream { outputStream ->
            outputStream.writeObject(o)
        }
    } catch (Exception e) {
        e.printStackTrace()
    }

}

// 拷貝文件
def copy(String sourcePath, String destationPath) {
    //判斷目標文件不存在,建立文件
    File destFile = new File(destationPath)
    try {
        if (!destFile.exists()) {
            destFile.createNewFile()
        }
    } catch (Exception e) {
        e.printStackTrace()
    }
    File sourceFile = new File(sourcePath)
    try {
        if (!sourceFile.exists()) {
            return
        }
    } catch (Exception e) {
        e.printStackTrace()
        return
    }

    def lines = sourceFile.readLines()
    destFile.withWriter {writer->
        lines.each {line->
            writer.append(line).append('\r\n')
        }
    }
}

複製代碼

參考連接

Groovy基礎

www.jianshu.com/p/8127742e0…

blog.csdn.net/liao_hb/art…

注:如有什麼地方闡述有誤,敬請指正。期待您的點贊哦!!!

相關文章
相關標籤/搜索