bingoogolapple.github.io
bingoogolapple.github.io copied to clipboard
Groovy
- 基于 JVM 的敏捷开发语言,有很多语法糖,很多在 Java 中必须要写的东西在 Groovy 中可以省略
- 可以与Java 完美结合,而且可以使用 Java 所有的库
- 语法上支持动态类型,闭包等新一代语言特性
- 既支持面向对象编程,也支持面向过程编程
- 既可以作为编程语言,也可以作为脚本语言
- 完全兼容 Java 语法
- 分号是可选的
- 类、方法默认是 public 的
- 编译器给属性自动添加 getter/setter 方法
- 在方法和闭包中,最后一个表达式的值会被作为返回值,可以省略 return
- == 等同于 equals,不会有 NullPointerExceptions
- 调用方法时括号时可选的
变量定义
// 弱类型定义方式:用 def 定义变量时可以动态类型转换
def a = 1
println a.class // class java.lang.Integer
a = 3.14
println a.class // class java.math.BigDecimal
a = "BGA"
println a.class // class java.lang.String
// 也可以不用 def,直接给变量赋值
b = 3.14
println b.class // class java.math.BigDecimal
b = "BGA"
println b.class // class java.lang.String
// 强类型定义方式:用具体类型定义变量时,同父类型可以转换,和 Java 一样
int c = 1
println c.class // class java.lang.Integer
c = 3.14
println c // 3
println c.class // class java.lang.Integer 不会被转换成 java.math.BigDecimal
c = "BGA"
println c.class
/*
Caught: org.codehaus.groovy.runtime.typehandling.GroovyCastException: Cannot cast object 'BGA' with class 'java.lang.String' to class 'int'
org.codehaus.groovy.runtime.typehandling.GroovyCastException: Cannot cast object 'BGA' with class 'java.lang.String' to class 'int'
at study.variable.run(variable.groovy:18)
*/
- 用具体类型定义变量时,同父类型可以转换,和 Java 一样
- 用 def 定义变量时可以动态类型转换
- 用于自己类或模块时用 def 定义。用于其他类或模块时用强类型定义方式
数字
int a = 10
println a.class // class java.lang.Integer
println 10.class // class java.lang.Integer
float b = 3.14
println b.class // class java.lang.Float
double c = 3.14
println c.class // class java.lang.Double
println 3.14f.class // class java.lang.Float
println 3.14.class // class java.math.BigDecimal
println 3.class // class java.lang.Integer
short d = 1
println d.class // class java.lang.Short
byte e = 1
println e.class // class java.lang.Byte
def f = 11
println f.class // class java.lang.Integer
def g = 3.14f
println g.class // class java.lang.Float
def h = 3.14
println h.class // class java.math.BigDecimal
// 这里的加号是 NumberNumberPlus 的 plus 方法
println 5.889f + 5.889f // 11.777999877929688 // 最终会转换成 Double 的 add 方法
println 5.889 + 5.889 // 11.778 最终会转换成 BigDecimal 的 add 方法
println 5.889.add(5.889) // 11.778
- 没有基本类型,全都是包装类型
- 整数默认是 java.lang.Integer
- 小数默认是 java.math.BigDecimal
- 所有的数字都继承自 java.lang.Number
字符串
- 基础用法
String a = "B\"G\"A"
println a.class // class java.lang.String
def b = "B'G'A"
println b.class // class java.lang.String
def c = 'B"G"A'
println c.class // class java.lang.String
// 原样输出,开始的'''后面和结束的'''前面巧回车时输出会自动换行,不想自动换行的话加上反斜线
def d = '''
BGA
BGA
BGA\
'''
println d.class // class java.lang.String
println d
def e = "bingoogolapple$c${(2 + 3) * 5}${"hello".capitalize()}" // 支持任意表达式
println e // bingoogolappleBGA25Hello
println e.class // class org.codehaus.groovy.runtime.GStringImpl Groovy 中特有的 GString
def f = echo1(e)
println f.class // class java.lang.String
def g = echo2(e)
println g.class // class org.codehaus.groovy.runtime.GStringImpl
def h = echo2(b)
println h.class // class java.lang.String
// static String echo1(def message) { // 不管传入的是 String 还是 GString,返回的始终是 String
// static def echo1(String message) { // 不管传入的是 String 还是 GString,返回的始终是 String
static String echo1(String message) { // 不管传入的是 String 还是 GString,返回的始终是 String
return message
}
static def echo2(def message) { // 传入什么类型返回的就是什么类型
return message
}
// 三个单引号时不支持表达式拼接
def i = '''
BGA
BGA${(11 + 22) / 3}
BGA\
'''
println i.class
println i
// 三个双引号时支持任意表达式拼接
def j = """
BGA
BGA${(11 + 22) / 3}
BGA\
"""
println j.class // class org.codehaus.groovy.runtime.GStringImpl
println j
- 常用方法
/*
三个来源:
java.lang.String
DefaultGroovyMethods
StringGroovyMethods
*/
// 填充到指定长度,第二个参数为要填充的值,默认填充空格
println '1111'.center(8, '2') // 22111122
println '11111'.center(8, '2') // 21111122
println '1111'.padLeft(8, '2') // 22221111
println '1111'.padRight(8, '2') // 11112222
println '1111'.leftShift('2') // 11112 leftShift 可以用 << 操作符替换
println '1111' << '2' // 11112 // 内部实现 new StringBuffer('1111').append('2')
// 从左边第一个字符开始比较,如果前面的字符都相等则比较长度
println '111'.compareTo('22') // -1 等价于操作符 <=>
println '111' <=> '22' // -1
println '111' > '22' // false
println '3' > '22' // true
println '22' <=> '22' // true
println 'BGA'.charAt(0) // B 等价 [0] 来获取
println 'BGA'[0] // B
println 'BGA'[0, 1] // BG 逗号分隔,获取指定1个或多个位置的值
println 'BGA'[0, 2] // BA 逗号分隔,获取指定1个或多个位置的值
println 'BGA'[1..2] // BGA .. 分隔,获取指定返回的值
println 'bingoogolapple' - 'apple' - 'bingo' // ogol
println 'hello world'.capitalize() // Hello world 句子首字母大写
println 'hello world'.split(' ').collect { it.capitalize() }.join(' ') // Hello World 每个单词首字母大写
println 'HELLO WORLD'.uncapitalize() // hELLO WORLD 句子首字母小写
println 'HELLO WORLD'.split(' ').collect { it.uncapitalize() }.join(' ') // hELLO wORLD 每个单词首字母小写
println 'BGA'.reverse() // AGB
println 'BGA'.asBoolean() // true 对比长度是否大于 0
println 'BGA'.toBoolean() // false 对比是否为字符串 true、y、0
闭包
def helloClosure1 = { param ->
println "Hello Closure $param"
}
println helloClosure1.class // class cn.bingoogolapple.dsl.groovy.7_closure$_run_closure1
helloClosure1.call('bingo')
helloClosure1('googol')
helloClosure1 'apple'
def helloClosure2 = {
println "Hello Closure $it" // 默认参数名叫 it
}
helloClosure2 'bingo'
def helloClosure3 = { name, age ->
println "Hello Closure $name $age"
}
def helloClosure4 = { String name, int age ->
println "Hello Closure $name $age"
}
helloClosure3('BGA', 26)
helloClosure4('BGA', 26)
helloClosure4.call(["wanghao", 26]) // 也可以通过 List 来返回多个参数
helloClosure4(["wanghao", 26])
// 闭包一定是有返回值的
def helloClosure5 = {
println "Hello Closure5"
}
def helloClosure6 = {
return "Hello Closure6"
}
def helloClosure7 = {
"Hello Closure7" // 如果没有写 return,则用最后一行的结果作为闭包的返回值
}
println helloClosure5() // null
println helloClosure6() // Hello Closure6
println helloClosure7() // Hello Closure7
static int factorial1(int number) {
int result = 1
1.upto(number, { num -> result *= num })
return result
}
println '------------------------------------'
println factorial1(3)
static int factorial2(int number) {
int result = 1
number.downto(1) { num -> result *= num } // 可以将最后一个闭包参数放到小括号外面
return result
}
println factorial2(3)
static int sum(int number) {
int result = 0
// 0 到 number - 1
number.times { num ->
result += num
// if (num == 1) {
// setDirective(Closure.DONE)
// }
}
return result
}
println sum(3)
println '------------------------------------'
def test = 'String Closure'
test.each {
print it.multiply(2)
}
test = '''\
line1
line2
line3\
'''
test.eachLine { line, counter -> // closure.call(new Object[]{line, counter}) 内部是通过对象数组返回参数的
println "$line | $counter"
}
println test.find { it.isNumber() } // 1
println test.findAll { it.isNumber() }.toListString() // [1, 2, 3]
println test.any { it.isNumber() } // true 字符串中只要有一个数字就是 true
println test.every { it.isNumber() } // false 字符串中所有的都是数字才为 true
println test.collect { it.toUpperCase() }
static def testClosureParams(Closure closure) {
println "parameterTypes ${closure.parameterTypes}"
println "maximumNumberOfParameters ${closure.maximumNumberOfParameters}"
if (closure.getMaximumNumberOfParameters() == 3) {
closure('bingoogolapple', 26, 'xxxxxx')
} else if (closure.getMaximumNumberOfParameters() == 2) {
closure.call('bingoogolapple', 26)
closure.call(['bingoogolapple', 26])
closure('bingoogolapple', 26)
closure(['bingoogolapple', 26])
} else {
closure.call('bingoogolapple')
}
}
testClosureParams { String name, int age, xxx ->
println "name $name, age $age, xxx $xxx"
}
testClosureParams { name, Integer age ->
println "name $name, age $age"
}
testClosureParams({ name ->
println "name $name"
})
/**
* this:代表闭包定义处的类或对象。静态闭包时为定义处的类,非静态时为定义处的类的实例对象
* owner:代表闭包定义处的类或对象。闭包嵌套闭包时,内层闭包的 owner 和 this 就会不一样,为外层闭包类的实例对象
* delegate:代表任意对象,默认与 owner 一致。人为修改 delegate 时,delegate 和 owner 时就会不一样
*
* owner 和 thisObject 都是构成方法传入的,不能修改
*/
class Tester {
static def classClosure = {
println "classClosure this:" + this // cn.bingoogolapple.dsl.groovy.Tester
println "classClosure owner:" + owner // cn.bingoogolapple.dsl.groovy.Tester
println "classClosure delegate:" + delegate // cn.bingoogolapple.dsl.groovy.Tester
println '----------------------------'
def innerClassClosure = {
println "innerClassClosure this:" + this // cn.bingoogolapple.dsl.groovy.Tester
println "innerClassClosure outerClosureClass: " + classClosure.class // cn.bingoogolapple.dsl.groovy.Tester$__clinit__closure4
println "innerClassClosure owner:" + owner // cn.bingoogolapple.dsl.groovy.Tester$__clinit__closure4@1dde4cb2
println "innerClassClosure delegate:" + delegate // cn.bingoogolapple.dsl.groovy.Tester$__clinit__closure4@1dde4cb2
println '--------------------------------------------------------'
}
innerClassClosure.call()
}
static def classMethod() {
def classMethodClosure = {
println "classMethodClosure this:" + this // cn.bingoogolapple.dsl.groovy.Tester
println "classMethodClosure owner:" + owner // cn.bingoogolapple.dsl.groovy.Tester
println "classMethodClosure delegate:" + delegate // cn.bingoogolapple.dsl.groovy.Tester
println '----------------------------'
def innerClassMethodClosure = {
println "innerClassMethodClosure this:" + this // cn.bingoogolapple.dsl.groovy.Tester
println "innerClassMethodClosure owner:" + owner // cn.bingoogolapple.dsl.groovy.Tester$_classMethod_closure2@5119fb47
println "innerClassMethodClosure delegate:" + delegate // cn.bingoogolapple.dsl.groovy.Tester$_classMethod_closure2@5119fb47
println '--------------------------------------------------------'
}
innerClassMethodClosure.call()
}
classMethodClosure.call()
}
def objectClosure = {
println "objectClosure this:" + this // cn.bingoogolapple.dsl.groovy.Tester@1afd44cb
println "objectClosure owner:" + owner // cn.bingoogolapple.dsl.groovy.Tester@1afd44cb
println "objectClosure delegate:" + delegate // cn.bingoogolapple.dsl.groovy.Tester@1afd44cb
println '----------------------------'
def innerObjectClosure = {
println "innerObjectClosure this:" + this // cn.bingoogolapple.dsl.groovy.Tester@1afd44cb
println "innerObjectClosure outerClosureClass: " + objectClosure.class // cn.bingoogolapple.dsl.groovy.Tester$_closure1
println "innerObjectClosure owner:" + owner // cn.bingoogolapple.dsl.groovy.Tester$_closure1@1ab3a8c8
println "innerObjectClosure delegate:" + delegate // cn.bingoogolapple.dsl.groovy.Tester$_closure1@1ab3a8c8
println '--------------------------------------------------------'
}
innerObjectClosure.call()
}
def objectMethod() {
def objectMethodClosure = {
println "objectMethodClosure this:" + this // cn.bingoogolapple.dsl.groovy.Tester@1afd44cb
println "objectMethodClosure owner:" + owner // cn.bingoogolapple.dsl.groovy.Tester@1afd44cb
println "objectMethodClosure delegate:" + delegate // cn.bingoogolapple.dsl.groovy.Tester@1afd44cb
println '----------------------------'
def innerObjectMethodClosure = {
println "innerObjectMethodClosure this:" + this // cn.bingoogolapple.dsl.groovy.Tester@1afd44cb
println "innerObjectMethodClosure owner:" + owner // cn.bingoogolapple.dsl.groovy.Tester$_objectMethod_closure3@479d31f3
println "innerObjectMethodClosure delegate:" + delegate // cn.bingoogolapple.dsl.groovy.Tester$_objectMethod_closure3@479d31f3
println '--------------------------------------------------------'
}
innerObjectMethodClosure.call()
}
objectMethodClosure.call()
}
}
Tester.classClosure.call()
Tester.classMethod()
def tester = new Tester()
tester.objectClosure.call()
tester.objectMethod()
def scriptOuterClosure = {
println "scriptOuterClosure this:" + this // cn.bingoogolapple.dsl.groovy.8_closureadvance@64cd705f
println "scriptOuterClosure owner:" + owner // cn.bingoogolapple.dsl.groovy.8_closureadvance@64cd705f
println "scriptOuterClosure delegate:" + delegate // cn.bingoogolapple.dsl.groovy.8_closureadvance@64cd705f
println '----------------------------'
def scriptInnerClosure = {
println "scriptInnerClosure this:" + this // cn.bingoogolapple.dsl.groovy.8_closureadvance@64cd705f
// println "scriptInnerClosure owner:$owner" // 在嵌套的内层 Closure 中,不能通过在字符串中直接使用 $owner 和 $delegate,否则会内存溢出
println "scriptInnerClosure owner:" + owner // cn.bingoogolapple.dsl.groovy.8_closureadvance$_run_closure2@c267ef4
println "scriptInnerClosure delegate:" + delegate // cn.bingoogolapple.dsl.groovy.8_closureadvance$_run_closure2@c267ef4
println '----------------------------'
}
def scriptInnerTwoClosure = {
println "scriptInnerTwoClosure this:" + this // cn.bingoogolapple.dsl.groovy.8_closureadvance@64cd705f
println "scriptInnerTwoClosure owner:" + owner // cn.bingoogolapple.dsl.groovy.8_closureadvance$_run_closure2@c267ef4
println "scriptInnerTwoClosure delegate:" + delegate // cn.bingoogolapple.dsl.groovy.Tester@1afd44cb
println "scriptInnerTwoClosure thisObject:" + thisObject // cn.bingoogolapple.dsl.groovy.Tester@1afd44cb
println '--------------------------------------------------------'
}
scriptInnerClosure.call()
scriptInnerTwoClosure.delegate = tester // 修改默认的 delegate
scriptInnerTwoClosure.call()
}
scriptOuterClosure.call()
class Student {
String name
def pretty = { "My name is ${name}" }
String toString() {
pretty.call()
}
}
class Teacher {
String name
}
def student = new Student(name: 'BGA')
def teacher = new Teacher(name: 'bingoogolapple')
println student.toString() // My name is BGA
student.pretty.delegate = teacher
println student.toString() // My name is BGA
// 修改解析策略,默认值为 Closure.OWNER_FIRST。学习委托策略时看源码中这几个常量对应注释中的 demo 更容易理解
student.pretty.resolveStrategy = Closure.DELEGATE_FIRST
println student.toString() // My name is bingoogolapple
- this 代表闭包定义处的类或对象。静态闭包时为定义处的类,非静态时为定义处的类的实例对象
- owner 代表闭包定义处的类或对象。闭包嵌套闭包时,内层闭包的 owner 和 this 就会不一样,为外层闭包类的实例对象
- delegate 代表任意对象,默认与 owner 一致。人为修改 delegate 时,delegate 和 owner 时就会不一样
- owner 和 thisObject 都是构成方法传入的,不能修改
- 修改解析策略(resolveStrategy)默认值为 Closure.OWNER_FIRST。学习委托策略时看源码中这几个常量对应注释中的 demo 更容易理解
- 在嵌套的内层 Closure 中,不能通过在字符串中直接使用 $owner 和 $delegate,否则会内存溢出
列表
def list = [1, 2, 3, 4, 5]
println list.class // class java.util.ArrayList
println list.size()
def array = [1, 2, 3, 4, 5] as int[]
println array.class // class [I
println array.length
int[] array2 = [1, 2, 3, 4, 5]
println array2.class // class [I
println array2.length
println '------------------------'
println list.sum {
it * 3
} // 每一项乘以 3 的和
list.add(6) // 末尾追加
println list
list.leftShift(7) // 末尾追加
println list
list << 8 // 末尾追加
println list
list.push(9) // 末尾追加
println list
println list.minus([1, 3, 5, 7, 9])
println list - [1, 3, 5, 7, 9]
println list
list.removeElement(1)
println list
list.removeAll { it % 2 == 0 }
println list
list.removeAll([7, 9])
println list
println '------------------------'
def sortList = [2, 8, 4, 6, 7, 9]
//sortList.sort() // 默认是升序
//println sortList
sortList.sort { a, b -> a == b ? 0 : a > b ? -1 : 1 }
println sortList
def sortStringList = ['kotlin', 'java', 'swift', 'python', 'shell', 'groovy']
sortStringList.sort { it -> return it.size() }
println sortStringList
def findList = [-1, 1, -2, 2, -3, 3, -4, 4]
println findList.find { return it % 2 == 0 }
println findList.findAll { return it % 2 != 0 }
println findList.any { return it % 2 != 0 } // true
println findList.every { return it % 2 == 0 } // false
println findList.min()
println findList.min { return Math.abs(it) }
println findList.max()
println findList.max { return Math.abs(it) }
println findList.count { return it % 2 == 0 }
list.each {
println "each $it"
}
list.forEach {
println "forEach $it"
}
list.eachWithIndex { element, index -> println "element $element, index $index" }
映射
def colors = [red: 'ff0000', green: '00ff00', blue: '0000ff']
println colors.getClass() // class java.util.LinkedHashMap
// println colors.class 不能用点操作符获取类型,map 的点操作符是获取对应 key 的值
println colors['red']
println colors.red
colors.yellow = 'ffff00'
println colors
colors.complex = [bingo: 1, googol: 2]
println colors
def students = [
1: [number: '0001', name: 'Bob',
score : 55, sex: 'male'],
2: [number: '0002', name: 'Johnny',
score : 62, sex: 'female'],
3: [number: '0003', name: 'Claire',
score : 73, sex: 'female'],
4: [number: '0004', name: 'Amy',
score : 66, sex: 'male']
]
println '\n----------------------------------------------------------'
students.each { student -> println "each entry | key $student.key, value $student.value" }
println '----------------------------------------------------------'
students.each { key, value -> println "each key value | key $key, value $value" }
println '----------------------------------------------------------'
students.eachWithIndex { student, index -> println "eachWithIndex entry | key $student.key, value $student.value, index $index" }
println '----------------------------------------------------------'
students.eachWithIndex { key, value, index -> println "eachWithIndex key value | key $key, value $value, index $index" }
println '----------------------------------------------------------\n'
def entry = students.find { studentEntry -> studentEntry.value.score >= 60 }
println entry.class
println entry
def resultMap = students.findAll { studentEntry -> studentEntry.value.score >= 60 }
println resultMap.getClass()
println resultMap
println students.count { studentEntry -> studentEntry.value.score >= 60 && studentEntry.value.sex == 'male' }
println students.findAll { studentEntry -> studentEntry.value.score >= 60 }.collect { it.value.name }.toListString()
println students.groupBy { studentEntry -> studentEntry.value.score >= 60 ? '及格' : '不及格' }
def sortedMap = students.sort { studentEntry1, studentEntry2 ->
def score1 = studentEntry1.value.score
def score2 = studentEntry2.value.score
return score1 == score2 ? 0 : score1 < score2 ? -1 : 1
} // 返回一个新的 map,老的 map 没变
println sortedMap
范围
def range = 1..10
println range.class // class groovy.lang.IntRange
println range
println range[0]
println range.from
println range.to
println range.contains(10) // true
range = 1..<10
println range.contains(10) // false
range.each { println it }
for (value in range) {
println value
}
static def getGrade(def number) {
def result
switch (number) {
case 0..<60:
result = '不及格'
break
case 60..<70:
result = '及格'
break
case 70..<80:
result = '良好'
break
case 80..100:
result = '优秀'
break
}
// return result
result // 最后一行可以省略 return 关键字
}
println getGrade(59)
println getGrade(60)
println getGrade(90)
面向对象
interface Action {
// protected void eat() // 接口中不许定义非 public 的方法
void eat()
void drink()
void play()
}
trait DefaultAction {
abstract void eat()
void drink() { // 可以有默认的实现
println "drink"
}
void play() {
println "play"
}
}
// groovy 中默认都是 public
class Person implements Serializable, DefaultAction {
String name
Integer age
def increaseAge(Integer years) {
this.age += years
}
// 1.类中有对应的方法直接调用类中对应的方法
// 2.类中没有对应的方法,MetaClass 中有则调用 MetaClass 中的方法
// 3.类中没有对应的方法,MetaClass 中也没有对应的方法,有重写 methodMissing 方法则调用 methodMissing 方法
def methodMissing(String name, Object args) {
return "the method ${name} is missing, the params is ${args}"
}
// 4.类中没有对应的方法,MetaClass 中也没有对应的方法,没有有重写 methodMissing 方法,有重写 invokeMethod 方法则调用 invokeMethod 方法
def invokeMethod(String name, Object args) {
return "the method is ${name}, the params is ${args}"
}
// 5.类中没有对应的方法,MetaClass 中也没有对应的方法,没有有重写 methodMissing 和 invokeMethod 方法,抛 MissingMethodException
@Override
void eat() {
println "eat"
}
}
def person = new Person()
// 没有对应构造方法时,可以通过名称参数来实例化
person = new Person(name: 'BGA')
person = new Person(age: 26)
person = new Person(name: 'BGA', age: 26)
// 无论是直接用点操作符还是调用 get/set 方法,最终都是调用 get/set 方法
println "the name is $person.name, the age is $person.age"
person.increaseAge(2)
println "the name is ${person.getName()}, the age is ${person.getAge()}"
//ExpandoMetaClass.enableGlobally()
// 为类动态添加属性
Person.metaClass.sex = 'male'
println person.sex // 动态增加属性只对修改 metaClass 后创建的对象生效,修改之前已经创建的对象不会生效
person = new Person(name: 'BGA', age: 26, sex: 'qwer')
println person.sex // qwer
person = new Person(name: 'BGA', age: 26)
println person.sex // male
person.sex = 'female'
println person.sex // female
// 为类动态添加方法
Person.metaClass.testSdf = { param1, param2 ->
println "param1 $param1, param2 $param2"
return name.toLowerCase()
}
println person.testSdf('aaaa', 'bbbb') // 动态增加方法对修改 metaClass 前后创建的对象都生效
person = new Person(name: 'ABC', age: 26)
println person.testSdf('aaaa', 'bbbb')
// 为类动态的添加静态方法
Person.metaClass.static.createPerson = { name, age -> new Person(name: name, age: age, sex: 'female') }
person = Person.createPerson('AAAABBBB', 26)
println "name $person.name, age $person.age, sex $person.sex"
JSON 解析
import groovy.json.JsonOutput
import groovy.json.JsonSlurper
def list = [new Person(name: 'BGA', age: 26),
new Person(name: 'bingoogolapple', age: 26)]
def jsonStr = JsonOutput.toJson(list)
println JsonOutput.prettyPrint(jsonStr)
def jsonSlurper = new JsonSlurper()
println jsonSlurper.parseText(jsonStr)
def responseText = 'http://www.wanandroid.com/banner/json'.toURL().text
def responseJson = new JsonSlurper().parseText(responseText)
println responseJson.data[0].desc
XML 解析
import groovy.json.JsonSlurper
import groovy.xml.MarkupBuilder
def writeXml() {
def responseText = 'http://www.wanandroid.com/banner/json'.toURL().text
def responseJson = new JsonSlurper().parseText(responseText)
def stringWriter = new StringWriter()
// 用来生成 xml 数据的核心类
def xmlBuilder = new MarkupBuilder(stringWriter)
//根结点 ResponseData 创建成功
xmlBuilder.ResponseData() {
errorCode(responseJson.errorCode)
errorMsg(responseJson.errorMsg)
data() {
responseJson.data.each {
banner(desc: it.desc, id: it.id, title: it.title, it.imagePath)
}
}
}
println stringWriter
}
writeXml()
println '------------------------------------------------------------------------'
def xmlStr = '''\
<ResponseData>
<errorCode>0</errorCode>
<errorMsg></errorMsg>
<data>
<banner desc='最新项目上线啦~' id='13' title='最新项目上线啦~'>http://www.wanandroid.com/blogimgs/5ae04af4-72b9-4696-81cb-1644cdcd2d29.jpg</banner>
<banner desc='' id='6' title='我们新增了一个常用导航Tab~'>http://www.wanandroid.com/blogimgs/62c1bd68-b5f3-4a3c-a649-7ca8c7dfabe6.png</banner>
<banner desc='一起来做个App吧' id='10' title='一起来做个App吧'>http://www.wanandroid.com/blogimgs/50c115c2-cf6c-4802-aa7b-a4334de444cd.png</banner>
<banner desc='' id='7' title='送你一个暖心的Mock API工具'>http://www.wanandroid.com/blogimgs/ffb61454-e0d2-46e7-bc9b-4f359061ae20.png</banner>
<banner desc='' id='4' title='看看别人的面经,搞定面试~'>http://www.wanandroid.com/blogimgs/ab17e8f9-6b79-450b-8079-0f2287eb6f0f.png</banner>
<banner desc='' id='3' title='兄弟,要不要挑个项目学习下?'>http://www.wanandroid.com/blogimgs/fb0ea461-e00a-482b-814f-4faca5761427.png</banner>
<banner desc='加个友情链接吧~' id='11' title='加个友情链接吧~'>http://www.wanandroid.com/blogimgs/84810df6-adf1-45bc-b3e2-294fa4e95005.png</banner>
<banner desc='' id='2' title='JSON工具'>http://www.wanandroid.com/blogimgs/90cf8c40-9489-4f9d-8936-02c9ebae31f0.png</banner>
<banner desc='' id='5' title='微信文章合集'>http://www.wanandroid.com/blogimgs/acc23063-1884-4925-bdf8-0b0364a7243e.png</banner>
</data>
</ResponseData>\
'''
def xmlSluper = new XmlSlurper()
// 返回的就是根节点 ResponseData
def xmlResponse = xmlSluper.parseText(xmlStr)
println xmlResponse.getClass() // class groovy.util.slurpersupport.NodeChild
println xmlResponse.errorCode
println xmlResponse.data.banner[0].@desc // 取属性用 @ 开头
println xmlResponse.data.banner[0].text() // 取值用 text()
println '------------------------------------------------------------------'
def titleList = []
xmlResponse.data.banner.each { banner ->
if ([email protected]().contains('3')) {
titleList.add([email protected]())
}
}
println titleList.toListString()
println '------------------ 深度遍历 xml 数据 ------------------'
// 不 collect 时拿到的是最里面子结点的文本
def contentList = xmlResponse.depthFirst().findAll { banner -> [email protected]().contains('3') }
println contentList.toListString()
// 单引号里两个星号也表示深度遍历
println xmlResponse.'**'.findAll { banner -> [email protected]().contains('3') }
println xmlResponse.'**'.find { banner -> [email protected]().contains('3') }.@title
titleList = xmlResponse.depthFirst().findAll { banner ->
[email protected]().contains('3')
}.collect { banner ->
return [email protected]()
}
println titleList
println '------------------ 广度遍历 xml 数据 ------------------'
titleList = xmlResponse.data.children().findAll { banner ->
[email protected]().contains('3')
}.collect { banner ->
return [email protected]()
}
println titleList
// 单引号里两个星号也表示广度遍历
println xmlResponse.data.'*'.findAll { banner ->
[email protected]().contains('3')
}.collect { banner ->
return [email protected]()
}
文件操作
import groovy.json.JsonSlurper
import groovy.xml.MarkupBuilder
def test1() {
def file = new File("WanAndroidBanner.json")
//file.eachLine {
// println it
//}
//println file.readLines()
println file.text
}
//test1()
def test2() {
def file = new File("WanAndroidBanner.json")
// 读取文件部分内容。Groovy 已经在内部关闭了流,开发者不需要在外面再次关闭
def reader = file.withReader { reader ->
char[] buffer = new char[100]
reader.read(buffer)
return buffer
}
println reader
}
//test2()
def copy(String sourcePath, String destPath) {
try {
def destFile = new File(destPath)
if (!destFile.exists()) {
destFile.createNewFile()
}
new File(sourcePath).withReader { reader ->
def lines = reader.readLines()
destFile.withWriter { writer ->
lines.each { line ->
writer.append(line + "\r\n")
}
}
}
return true
} catch (Exception e) {
e.printStackTrace()
}
return false
}
def test3() {
copy('WanAndroidBanner.json', 'WanAndroidBanner2.json')
println new File('WanAndroidBanner2.json').text
new File('WanAndroidBanner2.json').deleteOnExit()
}
//test3()
def saveObject(Object obj, String destPath) {
try {
def destFile = new File(destPath)
if (!destFile.exists()) {
destFile.createNewFile()
}
destFile.withObjectOutputStream { ObjectOutputStream out ->
out.writeObject(obj)
}
return true
} catch (Exception e) {
e.printStackTrace()
return false
}
return false
}
def readObject(String path) {
def obj = null
try {
def file = new File(path)
if (file == null || !file.exists()) return null
file.withObjectInputStream { input ->
obj = input.readObject()
}
} catch (Exception e) {
e.printStackTrace()
}
return obj
}
def test4() {
def filePath = 'person.bin'
def person = new Person(name: 'BGA', age: 26)
saveObject(person, filePath)
def result = (Person) readObject(filePath)
println "the name is ${result.name} and the age is ${result.age}"
new File(filePath).deleteOnExit()
}
//test4()
def writeXml() {
def responseText = 'http://www.wanandroid.com/banner/json'.toURL().text
def responseJson = new JsonSlurper().parseText(responseText)
new File('WanAndroidBanner.xml').withWriter { writer ->
// 用来生成 xml 数据的核心类
def xmlBuilder = new MarkupBuilder(writer)
//根结点 ResponseData 创建成功
xmlBuilder.ResponseData() {
errorCode(responseJson.errorCode)
errorMsg(responseJson.errorMsg)
data() {
responseJson.data.each {
banner(desc: it.desc, id: it.id, title: it.title, it.imagePath)
}
}
}
}
}
writeXml()