Groovy入门学习[脚本编程入门]

Groovy图标
Apache Groovy is a powerful, optionally typed and dynamic language, with static-typing and static compilation capabilities, for the Java platform aimed at improving developer productivity thanks to a concise, familiar and easy to learn syntax. It integrates smoothly with any Java program, and immediately delivers to your application powerful features, including scripting capabilities, Domain-Specific Language authoring, runtime and compile-time meta-programming and functional programming.

看官网图标就不简单,这门语言及其特殊,综合多门语言的语法特点,既能用编译型语言的语法书写,也能按脚本语言的语法书写,即有编程语言风格,也有脚本语言特色。使用脚本式风格属性,还可以用不同风格方式表达。继承了Java语言,理论上使用Java写的,Groovy也能正常编译通过。貌似编译是Java编译,先把Groovy转换成Java后再编译。

官网文档:Apache Groovy

使用 -D file.encoding 参数来设置脚本的默认编码

groovy -D file.encoding=UTF-8  .\test.groovy

脚本中获取编码:
println("Default encoding is: " + System.getProperty("file.encoding"))

怎么查看数据类型

def myVar = "Hello"
println(myVar.getClass())

1 注释和变量定义

注释分单行注释和多行注释

单行注释://
多行注释:/* ... */

使用 def 定义变量的时候,会自动转换为对应类型

引用变量不存在会报错:println(var)/println(“${var}”)

变量定义
自动识别:
def x = 5
def y = “hello world”

指定变量类型,如:Boolean, BigDecimal, Integer, Float, Double, String, ArrayList(List), LinkedHashMap(Map), 指定了变量类型不能把其他类型的值赋值给它 !!
数值:Integer/BigDecimal

示例:

Boolean a = "true"
BigDecimal b = 20
Integer c = 30
Integer c1 = 30.8  // 会自动转换为整形
Float d = 12.8
String e = "ok"
List f = [1,2,3]
Map g = ["name": "star", "age": 18]
Double h = 12.346

println(a)
println(b)
println(c)
println(c1)
println(d)
println(e)
println(f)
println(g)
println(h)

// true
// 20
// 30
// 30
// 12.8
// ok
// [1, 2, 3]
// [name:star, age:18]
// 12.346

2 数据类型及方法

Groovy 支持以下数据类型:

  1. 基本数据类型:byte、short、int、long、float、double、boolean、char
  2. 对象数据类型:String、BigDecimal、BigInteger、Date、Time、Timestamp、File、URL、Map、List、Set、Range、Pattern、Matcher、Closure、Class、Object 等
  3. 特殊数据类型:null、void

需要注意的是,Groovy 是一种动态类型语言,变量的数据类型可以在运行时动态改变。因此,Groovy 的数据类型比 Java 更加灵活。

类型:数值/字符串/列表/映射/范围(数组 def tup = (1…5))

定义布尔类型:boolean result = 3 > 5

2.1 运算符

算术运算符:加减乘除取模
赋值运算符:= += -= *= /=
自增自减运算符:++ –
关系运算符:大于/大于等于/小于/小于等于
等于运算符:等于== 不等于!= ,计算结果是布尔值. <=> 符号 "hello"<=>"hellq" 值为-1, 5<=>6 值为-1, 5<=>2 值为 1,也就是前面与后面比较,大于就是 1,小于就是-1,等于就是 0
逻辑运算符:

println(! (3 > 5))      // true
println( 3 > 2 && 3 > 5) // false
println( 3 > 2 || 3 >5)  // true

三元运算符(条件运算符):

println( false?false:true)
println(3<2?false:3>5?true:false) // 3<2 是false,false取冒号后面的值,(冒号后面计算3>5?true:false,3>5是false,取fasle)
println(3<2?false:3<5?true:false)
// true
// false
// true

2.2 数值

整数:正数/零/负数
浮点数:正/负浮点数

整数运算符:加减乘除/取模
浮点数运算符:加减乘除
整数与浮点数:加减乘除

2.3 字符串-不可变对象

使用引号将字符串包裹起来,可以使用单引号/双引号/三引号,三引号可以包含多行文本
注意: 跟 shell 一样,使用$引用变量,单引号不会解释变量

字符串索引:
索引从 0 开始,var[3]/var[-1],var[1..3]是 1 到 3 包含 3,var[1..<3]不包含 3,var[4..2]反向,var[2,1,6]取第 2/1/6 个字符

基本操作:
数学符号:加减乘

比较字符串: 等于/不等于/<=>

基本函数:
.size() 字符个数
.length() 字符长度,2 个含义相同
.count(‘x’) 统计 x 的数量
.contains(“hello”) 返回布尔值,是否包含 hello
.center(字符串,填充符号)
.compareToIgnoreCase(字符串) 跟字符串比较大小,按词典顺序比较,返回整形
.endsWith(字符串)
.equalsIgnoreCase(字符串) 返回 bool 值
.matches(正则) 全部匹配才返回 true
.replaceAll(正则,闭包函数)
.reverse()反转
.split(正则)
.strim() 去除字符串前后空格
.substring(开始,结束)
.toCharacter
.toDouble
.toFloat
.toInteger
.toLong
.toLowerCase
.toUpperCase
.tokenize()空格作为字符串分隔符,或传参给定字符串
.readLines(字符串)
.eachLine(闭包函数) eachLine(字符串,闭包函数)
eachLine 示例:

def func = {v -> print v}

def s = """hello
world
nice\n"""

func "hello"
print(s)
s.eachLine(func)

2.4 列表

重要:列表可以是任意元素的集合,数值/字符串/列表/映射/函数/对象(变量/类对象),列表跟字符串一样,索引从 0 开始

列表索引跟字符串一样

列表可以使用加法/减法/<<追加新元素

列表方法:
.add(元素) .add(索引,元素)
.addAll(元素集合)
.contains(元素) 返回 bool 值
.flatten() 子元素展开形成新列表
.getAt(索引) .getAt(range 对象)返回多个元素的列表 .getAt(指定多个子元素索引)
.intersect(列表) 交集
.isEmpty() 返回 bool 值
.pop() 删除最后一个元素
.remove(索引/元素值) 整数默认是索引,字符串或者其他默认是元素值
.size() 元素个数
.sort() 排序

2.5 映射

示例:

["name":"star", "age":18]
[2:[1,2] , 3:["name", "age"]]

def x = 1
def y = 2
def m = [x:y,y:x] 键是变量不会解析,值是变量会解析变量
println(m) # [x:2, y:1]

引用方法:m.x,m["x"]

方法:
.containsKey(键) 返回 bool 值
.get(键) 键不存在返回空, .get(键,默认值)
.keySet() 获取所有键集合,列表类型
.put(键,值)添加元素
.size()返回键值对个数
.values() 所有的值集合,collection 类型(List 也是集合类型一种), values().asList()返回列表

列表和映射的联合应用:

def library = [
    "Ken": ["Groovy", "UML"],
    "John": ["Java"]
]

library["Sally"] = ["Basic"]
library["John"] = library["John"]<<"Golang"
println("library: $library")
println "Ken has borrowed UML? ${library['Ken'].contains('UML')}"
println "borrowers number: ${library.size()}" 
println "borrowers:${library.keySet().sort()}" 
println "Ken borrowed books:${library["Ken"]}" 
println "library values: ${library.values()}"

// library: [Ken:[Groovy, UML], John:[Java, Golang], Sally:[Basic]]
// Ken has borrowed UML? true
// borrowers number: 3
// borrowers:[John, Ken, Sally]
// Ken borrowed books:[Groovy, UML]
// library values: [[Groovy, UML], [Java, Golang], [Basic]]

2.6 range-范围

示例:

1..100
1..<10
"a".."z"
10..1
"Z".."X"
1..5+3

def num = 1…10
举例:num.size()

方法:
.contains(元素) 返回 bool 值
.get(索引)
.getFrom() 获取第一个值
.getTo() 获取最后一个值
.isReverse() 是否逆序,bool 值
.size() 长度
.subList(from,to) 返回列表

3 正则表达式

定义正则:def reg =~ “hello”
部分匹配:=~
全部匹配:==~

元字符:

^ $ . * + ? {} []字符集 [^]非字符集 
(ab)*,ab出现任意次数 (a|b)*,a或b出现任意次数
元字符匹配要转义两个反斜杠\\ ,如:def reg =~ "\\.txt"
斜杆/包裹正则只需要单个斜杆,如: def reg =~ /\.txt/,含义同上

转义: \w 单词字符, \d 数字, \s 空字符, \W 非单词字符, \D 非数字, \S 非空白字符

正则案例:

import java.io.*

def s = "--11star 10:20PM"

def pt = '(\\w+)\\s+((\\d{1,2}):(\\d{2})([AP]M))'

def matcher1 = s =~ pt
println(matcher1.matches())  // 要整行匹配才是true,不是整行匹配可以输出matcher1[0]
println(matcher1)
println(matcher1[0])
println(matcher1[0][5])

// false
// java.util.regex.Matcher[pattern=(\w+)\s+((\d{1,2}):(\d{2})([AP]M)) region=0,16 lastmatch=]
// [11star 10:10PM, 11star, 10:10PM, 10, 10, PM]  // matcher1[0]是全部,1是第一个括号,2是后面的外边括号,3/4/5是里面的小括号
// PM

4 输入输出

print 输出不换号,print(“hello”) print “hello”,2 种写法,函数式和闭包式,可以输出任意类型的值
println 输出换行
print("hello world")
print("hello \n world")

格式化输出:printf
示例:

def a = "name"
def b = 18
def c = 60.8 // 在def定义的时候自动转换为对应类型,如果是60会报错

printf("name is %s,age is %d, weight is %.2f", [a,b,c])

name is name,age is 18, weight is 60.80

字符串格式化: %20s,%-20s(文字靠左)

基本输入:

def getString(){
    return System.console().readLine("请输入名字:")
}

def getInteger(){
    return System.console().readLine("your age:").toInteger()
}

def getWeight(){
    return System.console().readLine("your weight:").toDouble()
}

def name = getString()
def age = getInteger()
def weight = getWeight()
println("your name:$name, age: $age, weight: $weight")

// PS D:\my_document\vscode-project> groovy -D file.encoding=UTF-8  .\test.groovy 
// 请输入名字:star
// your age:18
// your weight:60
// your name:star, age: 18, weight: 60.0

5 自定义方法

简单输出:

def greeting(){
    println "hello world"
}

greeting()

// 多行语句可以分号隔开 print "hello";print " ";print "world"

内置变量:

def info(){
    def name = "star"
    def age = 18
    println("my name is $name, age is $age")
}

info()

外部传参:

def info(name, age){
    println("my name is $name, age is $age")
}

info("star", 18)

默认参数:

def info(name, age=20){
    println("my name is $name, age is $age")
}

info("star")

函数返回值:

def info(name, age=20){
    return "my name is $name, age is $age"
}

def s = info("star", 25)
println(s)

6 内置方法

assert(3 == 5),如果 bool 值为 FALSE,则断言失败,抛出异常

upto 方法:数字序列迭代

def sum = 0
1.upto(10){n -> sum += n}
println(sum)

each 方法:集合/字符串/列表/映射

def s = ''
"hello".each(){it -> s += it;s += "-"}
println(s)


[1,2,3,4].each(){it -> println it}

def m = ["Ken":18, "Sally":20]
m.each(){it -> println it}
m.each(){it -> println("${it.key} age is ${it.value}")}

// h-e-l-l-o-
// 1
// 2
// 3
// 4
// Ken=18
// Sally=20
// Ken age is 18
// Sally age is 20

each 配合 if 条件语句:

[1,2,3,4].each(){it -> if(it%2 ==0)println it}

// 2
// 4

find 方法,只返回查到的第一个元素:闭包必须返回 bool 值,所有返回 true 的元素形成一个新的元素集合

def lst = [1,2,3,4]
lst = lst.find(){it -> it > 2}
println(lst)

def m = ["Ken":18, "John":22, "Sally":24]
println(m)
m = m.find(){it -> it.value > 20}
println(m)
println(m.key)

// 3
// [Ken:18, John:22, Sally:24]
// John=22
// John

findAll 方法,只返回查到的所有元素:闭包必须返回 bool 值,所有返回 true 的元素形成一个新的元素集合

def lst = [1,2,3,4]
lst = lst.findAll(){it -> it > 2}
println(lst)

def m = ["Ken":18, "John":22, "Sally":24]
println(m)
m = m.findAll(){it -> it.value > 20}
println(m)
println(m.key)
println(m.keySet())

// [3, 4]
// [Ken:18, John:22, Sally:24]
// [John:22, Sally:24]
// null
// [John, Sally]

any 方法:每个元素迭代使用闭包函数返回值,类型为 bool,任意一个返回 true 则表达式为真,否则为假

def lst = [1,2,3,4]
def b = 'hello'
println(b)
b = lst.any(){it -> it > 0}  // b可以重新复制为布尔类型
println(b)

every 方法:每个元素迭代使用闭包函数返回值,类型为 bool,所有元素返回 true 则表达式为真,否则为假

def lst = [1,2,3,4]
def b = 'hello'
println(b)
b = lst.every(){it -> it > 0}
println(b)
b = lst.every(){it -> it > 3}
println(b)

collect 方法:所有元素经过闭包函数运算后,返回同样长度的新列表,类似于 Python 的 map 函数

def lst = [1,2,3,4]
lst = lst.collect(){it -> it * it}
println(lst)

// [1, 4, 9, 16]

inject 方法:把集合的第一个元素和第二个元素通过闭包计算,返回的结果再与第三个元素计算,以此类推,最后返回总的计算结果

def lst = [1,2,3,4]

def sum = lst.inject(){previous, element -> previous + element}
println(sum)  // 10

7 流程控制

三种流程控制结构:

  • 顺序
  • 选择
  • 迭代

7.1 while

基本结构:

while(condition){
	statement 1
	statement 2
}

def LIMIT = 5
def count = 1
while(count <= LIMIT){
    println count
    count++
}

7.2 for

循环可以是某个范围/集合(列表/映射/数组)
示例:

for(count in 1..3){
    println count
}

for (var in ['hello', 'world']){
    println var
}

def staff = ["Ken":20,"John":22, "Sally":18]
def total = 0
for(s in staff){
    total += s.value
}
println("ages: ${total}")

对数组做循环:

def tup = (1..5)
println(tup)
for(i in tup){
    println(i)
}

7.3 if

基本结构:

if(condition){
	statement 1
} 

if(condition){
	statement 1
} else {
	statement 2
}

if(condition1){
	statement 1
} 
else if (condition2) {
	statement 2
}
else if (condition3) {
	statement 3
}
else {
	statement 4
}

7.4 switch

基本结构:

switch(value) {
    case express 1:
        statement 1
        break
    case express 2:
        statement 2
        break
    case express 3:
        statement 3
        break
    default:
        statement 4
	    break
}

express 可以是范围(1..5)/字符串("hello")/列表([1,2,3])/正则(~[0-9]{3}

7.5 循环关键字:break/continue

break:可以用在 while/for/switch 语句中
continue:可以用在 while/for 循环中

8 闭包 closure

闭包函数可以直接使用外部变量,普通函数只能通过传参

闭包特性:

  1. 闭包可以当做函数使用
  2. 闭包可以作为其他函数的参数
  3. 闭包可以作为其他闭包的参数
  4. 闭包作为返回值
  5. 闭包作为列表元素
  6. 闭包可以定义在闭包函数中
def lst = [1,2,3,4]

def isEven = {param -> param%2 == 0}
def isOdd = {param -> param%2 != 0}

def elem = {num -> 
    if(num ==2){
        return isEven  // 闭包作为返回值
    } else if(num == 1){
        return isOdd
    }
}


def elemEven = elem(2)
def elemOdd = elem(1)
lst = lst.findAll elemOdd
println(lst)

def clos_list = [isEven, isOdd] //  闭包作为列表参数
println(clos_list)


// [1, 3]
// [test$_run_closure1@47f4e407, test$_run_closure2@2d1dee39]

闭包调用方法:

def closx = {println "hello ${it}"}

closx.call("Groovy")
closx "Groovy"
closx("Groovy")

无参闭包示例:

def clos = {println "hello world"}
clos()

有参闭包示例:

def clos = {param -> println param}
def closx = {param -> println("hello $param")}
clos("world")
closx("world")

单个参数可以隐藏:

def clos = {println it}
def closx = {println "hello ${it}"}
clos("world")
closx("world")

变量名称必须是it

调用外部变量:

def var = "hello"
def clos = {param -> println "$var world"}
clos()

闭包作为函数参数,闭包不会读取函数内部变量:

def greeting = "hello"
def closx = {param -> println "$greeting world"}

def demo(clos){
    def greeting = "nice"
    clos.call("star")
}

demo(closx)

函数调用闭包几种方法:

def greeting = "hello"
def closx = {param -> println "$greeting $param"}

def demo(clos){
    def greeting = "nice"
    clos.call("star")
}

// 第一种方法:
demo(closx)
// 第二种方法:
demo closx
// 第三种方法:
demo(){param -> println("good $param")}

闭包高级用法:

def lst = [1,2,3,4]

def doubles = {param -> 2 * param}
def triples = {param -> 3 * param}

def map(clos, list){
    return list.collect(clos)
}

println(map(doubles, lst))
println(map(triples, lst))

// [2, 4, 6, 8]
// [3, 6, 9, 12]

9 文件和命令行参数

获取命令行参数:

println "args: $args"
println "args num: ${args.size()}"
println "args 0: ${args[0]}"

// PS D:\my_document\vscode-project> groovy .\test.groovy hello world
// args: [hello, world]
// args num: 2
// args 0: hello
// PS D:\my_document\vscode-project> groovy .\test.groovy "hello world"
// args: [hello world]
// args num: 1
// args 0: hello world
// PS D:\my_document\vscode-project> groovy .\test.groovy "hello world" "love groovy"
// args: [hello world, love groovy]
// args num: 2
// args 0: hello world

文件处理方法:
append(字符串)将字符串追加到文件末尾
createNewFile() 创建一个新的空文档,当且仅当文件不存在时才能创建,返回布尔值,表示成功或失败
delete() 删除由路径表示的文件或目录,返回布尔值,不存在不会报错,目录不是空的无法删除,可以先用 eachFileRecurse 删除文件,再删除目录
eachFile(闭包函数)为指定目录的每个文件应用闭包函数
eachFileRecurse(闭包函数),功能同上,但是会递归去执行
eachLine(闭包函数)逐行遍历指定文档
exists() 判断指定路径是否存在文件或目录
getPath()将抽象路径转换为一个路径字符串,返回字符串
getText() 读取文本内容作为一个字符串返回
isDirectory()判断是否是一个目录,返回布尔值
mkdir()创建目录,返回布尔值
withPrintWriter(闭包函数)为文件创建一个新的 PrintWriter 方法,并传递给闭包,并在此确认文件是否被关闭

一行一行读取文件并显示:

import java.io.File 

if(args.size() != 1){
    println "Usage: script.groovy filename"
    System.exit(1)
} else {
    new File(args[0]).eachLine {line -> 
        println "Line: $line"
    }
}

// PS D:\my_document\vscode-project> groovy .\test.groovy "utf8.txt"
// Line: 这里是utf-8编码
// Line: fille encoding type is utf-8
// Line: 结束

读取文件返回字符串:

def s = new File(args[0]).getText()
println(s)

统计文件字符数/单词数/行数:

import java.io.File


def chars = 0
def words = 0
def lines = 0

new File("utf8.txt").eachLine {line ->
    chars += line.length()
    words += line.tokenize().size()
    lines++
}
println("chars:${chars},words:${words},lines:$lines")

// chars:40,words:7,lines:3

列出目录下所有文件:

import java.io.File 

def listDir(dirFile, indent){
    dirFile.eachFile {file ->
        (0..<indent).each {print " "}
        println "${file.getName()}"
        if (file.isDirectory()){
            listDir(file, 2+indent)
        }
    }
}

def printDir(dirName){
    listDir(new File(dirName), 0)
}

if (args.size() != 1 || new File(args[0]).isDirectory() == false){
    println("Usage: script.groovy directory")
    System.exit(1)
} else {
    printDir(args[0])
}

// PS D:\my_document\vscode-project> groovy -D file.encoding=UTF-8  .\test.groovy "test\\down"
// process.bat
// t-link.txt.lnk
// t.txt
// testdir
//   test.txt
//   testdir2
//     test2-1.txt
//     test2-2.txt
// 测试.txt

目录递归查找文件:

import java.io.File 

def printDir(dirName, size){
    new File(dirName).eachFileRecurse {file ->
        if(file.length() > size){
            println "${file.getName()}"
        }
    }
}

if (args.size() != 2 || new File(args[0]).isDirectory() == false){
    println "Usage: script.groovy dirname"
} else {
    printDir(args[0], args[1].toInteger())
}

// PS D:\my_document\vscode-project> groovy -D file.encoding=UTF-8  .\test.groovy "test\\down" 80
// process.bat
// t-link.txt.lnk
// test.txt

文件拷贝:

import java.io.*

if (args.size() != 2){
    println "Usage: script.groovy filename1 filename2"
    System.exit(1)
} else {
    def outFile = new File(args[1])
    if(outFile.exists()){
        outFile.delete()
    }

    def printWriter = outFile.newPrintWriter()
    new File(args[0]).eachLine {line ->
        printWriter.println(line)
    }
    printWriter.flush()
    printWriter.close()
}

文件拷贝方法 2:

import java.io.*

if (args.size() != 2){
    println "Usage: script.groovy filename1 filename2"
    System.exit(1)
} else {
    new File(args[1]).withPrintWriter  {printWriter ->
        new File(args[0]).eachLine {line ->
            printWriter.println(line)
        }
    }
}

10 解析 XML

使用正则匹配获取 project 属性:

import java.io.File


def file = "test.xml"

def re_pt = '\s*<project\\s+name="(\\S+)".*'

new File(file).eachLine {line ->
    matcher = line =~ re_pt
    if(matcher.matches()){
        println "name: ${matcher[0][1]}"
    }
}

示例 books.xml 文件:

<books>
  <book isbn="1234567890">
    <title>Java Programming</title>
    <author>John Smith</author>
  </book>
  <book isbn="0987654321">
    <title>Python Programming</title>
    <author>Jane Doe</author>
  </book>
</books>

Jenkins 中导入以下 4 个模块无报错:

import groovy.xml.MarkupBuilder 
import groovy.json.JsonSlurper
import groovy.util.XmlSlurper
import groovy.util.XmlParser 

解析 XML 文件

import groovy.util.XmlParser

def xml = new XmlParser().parse(new File('books.xml'))

xml.book.each { book ->
    println "Title: ${book.title.text()}"
    println "Author: ${book.author.text()}"
    println "ISBN: ${book.@isbn}"
    println "------------------------"
}

输出结果:

Title: Java Programming
Author: John Smith
ISBN: 1234567890
------------------------
Title: Python Programming
Author: Jane Doe
ISBN: 0987654321
------------------------

11 执行本地命令

import groovy.util.XmlParser 
import java.io.File 


def file = ".repo/manifest.xml"
file = "/home/build/jenkins/workspace/dynamic_gerrit_paramter_build_test/t.txt"
def prj_list = []
boolean b = new File(file).exists()
b = true
prj_list.add(b)

def command = ['pwd']
def processBuilder = new ProcessBuilder(command)
def process = processBuilder.start()

def reader = new BufferedReader(new InputStreamReader(process.inputStream))
def line
while ((line = reader.readLine()) != null) {
    prj_list.add(line)
}

process.waitFor()



// return ['master', 'feature', 'hotfix', 'develop']
return prj_list

Windows 执行命令:

def command = ['C:\\Windows\\System32\\cmd.exe', '/c', 'dir']
def processBuilder = new ProcessBuilder(command)
def process = processBuilder.start()


def reader = new BufferedReader(new InputStreamReader(process.inputStream))
def line
while ((line = reader.readLine()) != null) {
    println line
}

process.waitFor()


第二种方法:
def lst = []
def command = "ls -l"
def process = Runtime.getRuntime().exec(command)
process.waitFor()
reader = process.inputStream.text
reader.eachLine {line ->
    lst.add(line)
}

第三种方法:
def command = "ls -l"
def output = command.execute().text
// println output
output.eachLine { line ->
    if(line.size() > 0){
        hash_list.add(line)
    }
}

多次执行宿主机的命令:

def commands = [
    ['C:\\Windows\\System32\\cmd.exe', '/c', 'dir', 'ansi.txt', '/b'],
    ['C:\\Windows\\System32\\cmd.exe', '/c', 'type', 'ansi.txt'],
    ['C:\\Windows\\System32\\cmd.exe', '/c', 'dir',  'test.xml', '/b']
]

for (def command : commands) {
    def processBuilder = new ProcessBuilder(command)
    def process = processBuilder.start()
    def inputStream = process.inputStream
    def reader = new BufferedReader(new InputStreamReader(inputStream))
    reader.eachLine { line ->
        println(line)
    }
    process.waitFor()
}

获取当前服务器 IP:

import groovy.util.XmlParser 
import java.io.File 


def file = ".repo/manifest.xml"
file = "/home/build/jenkins/workspace/dynamic_gerrit_paramter_build_test/t.txt"
file = "/tmp"
def prj_list = []
boolean b = new File(file).exists()
prj_list.add(b)


def command = ['hostname', '-I']
def processBuilder = new ProcessBuilder(command)
def process = processBuilder.start()

def reader = new BufferedReader(new InputStreamReader(process.inputStream))
def line
while ((line = reader.readLine()) != null) {
    prj_list.add(line)
}

process.waitFor()

使用 groovy 脚本多次执行宿主机的命令:

def command = ['ls', '-l']
def processBuilder = new ProcessBuilder(command)

// 执行命令10次
for (int i = 0; i < 10; i++) {
    def process = processBuilder.start()
    def inputStream = process.inputStream
    def reader = new BufferedReader(new InputStreamReader(inputStream))
    reader.eachLine { line ->
        println(line)
    }
    process.waitFor()
}

获取当前年月日,时分秒,纳秒:

import java.time.LocalTime
import java.time.LocalDate

def now = LocalTime.now()
def hour = now.getHour()
def minute = now.getMinute()
def second = now.getSecond()

println("Current time is: ${hour}:${minute}:${second}")

def c_time = now.getHour().toString() + now.getMinute().toString() + now.getSecond().toString()
println("Current time is: ${c_time}")


now = LocalDate.now()
def year = now.getYear()
def month = now.getMonthValue()
def day = now.getDayOfMonth()

println("Current date is: ${year}-${month}-${day}")

def nanoTime = System.nanoTime()

println("Current nanoseconds is: ${nanoTime}")
println("nano to int: ${nanoTime.toInteger()}")

保存为 JSON 数据格式到文件:

import groovy.json.JsonBuilder

// 创建一个Map对象,用于存储数据
def data = [
    name: "John",
    age: 30,
    email: "john@example.com"
]

// 创建JsonBuilder对象,并将Map对象转换为JSON格式
def json = new JsonBuilder(data).toPrettyString()

// 创建File对象,并将JSON字符串写入文件
def file = new File("data.json")
file.write(json)
def printWriter = file.newPrintWriter()
printWriter.flush()
printWriter.close()

读取文件中的 JSON 数据:

import groovy.json.JsonSlurper

// 创建File对象,并读取文件中的JSON字符串
def file = new File("data.json")
def json = file.text

// 创建JsonSlurper对象,并将JSON字符串转换为Map对象
def slurper = new JsonSlurper()
def data = slurper.parseText(json)

// 输出Map对象中的数据
println "Name: ${data.name}"
println "Age: ${data.age}"
println "Email: ${data.email}"

Jenkins 中 tag 参数写入并读取代码(样例):

import groovy.json.JsonBuilder
import groovy.json.JsonSlurper
import java.io.File

def tag_dict = [:]
for (key in 1..4){
    key = "project/build/name" + key 
    def value_list = []
    for (value in 1..5){
        value = key + "-" + value
        value_list.add(value)
    }
    tag_dict.put(key, value_list)
}

def json = new JsonBuilder(tag_dict).toPrettyString()
def file = new File("/tmp/data.json")
file.write(json)

def file_read = new File("/tmp/data.json")
boolean b = file_read.exists()
def json_read = file_read.text

def slurper = new JsonSlurper()
def data_read = slurper.parseText(json_read)

return data_read[project]
// return tag_dict[project]

groovy 读取 JSON 文件,指定文件编码为 utf-8:

import groovy.json.JsonSlurper

def file = new File("path/to/your/json/file.json")
def reader = new InputStreamReader(new FileInputStream(file), "UTF-8")
def json = new JsonSlurper().parse(reader)

// 处理读取到的JSON数据

12 获取Gerrit仓库分支

参考文档:设置java.net.URL请求方式post get

都是groovy内置模块,无需额外安装,代码如下:

package test

import java.net.URL
import java.net.HttpURLConnection
import groovy.json.JsonSlurper


List list = []
String username = "admin"
String password = "123456"
String responseCookie = ""
String gerritLoginURL = "http://192.168.72.55:8080/login"
String gerritHomeURL = "http://192.168.72.55:8080"

// 仓库名称
String prjName = "android/kernel"

// 设置默认cookie handler,新创建连接自动添加handler中cookie
CookieManager cookieManager = new CookieManager()
CookieHandler.setDefault(cookieManager)

// 创建连接,设置请求方法
URL url = new URL(gerritLoginURL)
HttpURLConnection connection = (HttpURLConnection) url.openConnection()
connection.setDoOutput(true)
connection.setRequestMethod("POST")
connection.setRequestProperty("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64)")

// 发送POST请求,写入请求数据账号密码
String auth = String.format("username=%s&password=%s", username, password)
OutputStream os = connection.getOutputStream()
os.write(auth.toString().getBytes())
os.close()

// 获取连接状态及cookie
if(connection.responseCode == 200) {
	responseCookie = connection.getHeaderField("Set-Cookie")
} else {
	list.add("error")
	return list
}

//获取登录后的cookie
//println(connection.responseCode)
//List cookies = cookieManager.getCookieStore().getCookies();
//for (HttpCookie cookie : cookies) {
//	System.out.println(cookie);
//}

// 获取仓库分支数据
String branchText = ""
String gerritBranchURL = gerritHomeURL + "/projects/" + prjName.replace("/", "%2F") + "/branches/"
url = new URL(gerritBranchURL)
connection = (HttpURLConnection) url.openConnection()
if(connection.responseCode == 200) {
	branchText = connection.getInputStream().getText().replace(")]}'", "")
} else {
	list.add("error")
	return list
}

// 获取分支
JsonSlurper js = new JsonSlurper()
for (element in js.parseText(branchText)) {
	s = element.ref.toString()
	if(s.startsWith("refs/heads/")) {
		list.add(s.replace("refs/heads/", ""))
	}
}

println(list)

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
Groovy是一种基于Java平台的动态编程语言,它提供了许多方便的特性,例如闭包、动态类型、元编程等。在Java应用程序中,我们可以通过将Groovy脚本嵌入到Java代码中来实现更灵活的编程。具体来说,可以使用GroovyShell类来加载和执行Groovy脚本,也可以使用GroovyClassLoader类来动态加载Groovy类。 在使用Groovy脚本嵌入开发时,需要先编写Groovy脚本并保存为.groovy文件,然后在Java代码中加载并执行该脚本。例如,以下代码演示了如何加载并执行一个简单的Groovy脚本: ```java import groovy.lang.Binding; import groovy.lang.GroovyShell; public class GroovyScriptRunner { public static void main(String[] args) throws Exception { Binding binding = new Binding(); binding.setVariable("name", "World"); GroovyShell shell = new GroovyShell(binding); shell.evaluate(new File("hello.groovy")); } } ``` 在这个例子中,我们首先创建了一个GroovyShell对象,并将一个Binding对象传递给它。Binding对象可以用于在Java代码和Groovy脚本之间共享变量。然后,我们通过调用GroovyShell的evaluate方法加载并执行了一个名为hello.groovy脚本文件。 当我们需要在Java应用程序中动态生成类时,也可以使用Groovy脚本来实现。Groovy提供了一个方便的@CompileStatic注解,可以使得Groovy类在编译时就能够被静态化,并且可以直接在Java代码中使用。以下是一个使用@CompileStatic注解的例子: ```groovy import groovy.transform.CompileStatic @CompileStatic class MyGroovyClass { static int add(int x, int y) { return x + y } } ``` 在Java代码中,我们可以直接使用该Groovy类: ```java import org.codehaus.groovy.control.CompilerConfiguration; import groovy.lang.GroovyClassLoader; public class GroovyClassGenerator { public static void main(String[] args) throws Exception { CompilerConfiguration config = new CompilerConfiguration(); config.setTargetDirectory("target/classes"); GroovyClassLoader loader = new GroovyClassLoader( GroovyClassGenerator.class.getClassLoader(), config); Class<?> clazz = loader.parseClass(new File("MyGroovyClass.groovy")); int result = (int) clazz.getDeclaredMethod("add", int.class, int.class) .invoke(null, 1, 2); System.out.println(result); } } ``` 在这个例子中,我们使用GroovyClassLoader的parseClass方法动态加载了MyGroovyClass.groovy文件,并使用反射方式调用了其中的add方法。在这个过程中,MyGroovyClass类已经被编译成了Java字节码文件,并被保存在了指定的目录中。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Effordson

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值