Jenkins pipeline 脚本语言学习支持

1 引言

Groovy是用于Java虚拟机的一种敏捷的动态语言,它是一种成熟的面向对象编程语言,既可以用于面向对象编程,又可以用作纯粹的脚本语言。 使用该种语言不必编写过多的代码,同时又具有闭包和动态语言中的其他特性。

Groovy是一种基础JVM(Java虚拟机)的敏捷开发语言,他结合了Python、Ruby和Smalltalk的特性,Groovy代码能够于Java代码很好的结合,也能用于扩展现有代码。 由于其运行在JVM的特性,Groovy可以使用其他Java语言编写法的库。

for(int i=0; i<10; i++) {
    ...
}

10.times{
    ...
}

在使用Groovy编程时,Java有的Groovy几乎都有。Groovy同样扩展了java.lang.Object类,Groovy类就是Java类,Java语义都保留下来了,所以使用Groovy编写的表达式和语句, 对于Java程序员而言,理解它没有任何障碍。
Jenkins pipeline 脚本语言学习支持_第1张图片
Jenkins pipeline 脚本语言学习支持_第2张图片
Groovy虽然支持Java的语法但它并没有强迫我们学习新的类和库,而是通过向JDK中各种类添加方法,所以说Groovy扩展了JDK,这些扩展称之为GDK (Groovy JDK)。

Java中可以使用java.lang.process与系统级进程进行交互,例如,我们在代码中调用git的help命令并把help的内容打印出来,用Java的实现代码如下:

package com.zs.groovy;


import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;

public class ExecuterProcessor {
    public static void main(String[] args) {
        try {
            // 获取process实例
            Process process = Runtime.getRuntime().exec("git help");
            // 读取输入流
            BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()));
            String line = "";
            while ((line = reader.readLine()) != null) {
                System.out.println(line);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

转化为 groovy 语法:

print "git help".execute().text

2 基本语法

2.1 标识符

Jenkins pipeline 脚本语言学习支持_第3张图片

2.2 字符串

Groovy允许实例化java.lang.String类来定义一个字符串对象,同样地,也可以通过实例化groovy.lang.GString类定义一个字符串对象,两者可以混合使用。

def a = 'i am zhaoshuai-lc'
def b = '''
    i am zhaoshuai-lc
    and
    i am a male
'''
// 说明:用单引号或三个单引号定义的字符串不支持混合编程

def c = "hello zhaoshuai-lc"
> def name = "zhaoshuai-lc"
> def _name = "hello ${name}"
> print _name
hello zhaoshuai-lc

三个双引号引起来的字符串:
用"""引号引起来的字符串行为上和双引号引起来的字符串是一样的,不同之处在于它代表多行字符串,就像三个单引号定义的字符串。例如:

def name = 'zhaoshuai-lc'
def template = """
    Dear $name
    i love U
"""
print(template)

如果是使用内置变量类型定义的变量,一经定义,后面是不可以更改变量类型的。但是Groovy也提供了类似javascript中的any定义任意变量类型的关键字def。

class Example { 
   static void main(String[] args) { 
      def _Name = 1;
      _Name="it飞牛"; 
      println(_Name);
   } 
}
//打印如下:
it飞牛

Jenkins pipeline 脚本语言学习支持_第4张图片

2.3 数值类型

byte -这是用来表示字节值。例如2。
short -这是用来表示一个短整型。例如10。
int -这是用来表示整数。例如1234。
long -这是用来表示一个长整型。例如10000090。
float -这是用来表示32位浮点数。例如12.34。
double -这是用来表示64位浮点数,这些数字是有时可能需要的更长的十进制数表示。例如12.3456565。
char -这定义了单个字符文字。例如“A”。
Boolean -这表示一个布尔值,可以是true或false。
String -这些是以字符串的形式表示的文本。例如,“Hello World”。

Jenkins pipeline 脚本语言学习支持_第5张图片
Jenkins pipeline 脚本语言学习支持_第6张图片
不同类型数值进行算术运算的规则:
对于二元运算符,两个不同类型的数值进行运算后它们的结果按照以下规则确定
对于byte、char、short、int这几种类型之间运算的结果为int
涉及long与byte、char、short、int之间运算的结果为long
涉及BigInteger与其它类型数值之间的运算结果为BigInteger
BigDecimal与byte、char、short、int之间的运算结果为BigDecimal
float、double与BigDecimal之间的运算结果为double
两个BigDecimal之间的运算结果为BigDecimal

2.4 数组与集合

Groovy没有自己的集合类型,它的List类型实际上用的就是JDK中的java.util.List包。当我们定义一个集合对象,Groovy默认采用Java.util.ArrayList类型。

> def numbers = [1, 2, 3]
> assert numbers instanceof java.util.List
> assert numbers.size() == 3

也可以在集合中放置不同类型的元素,例如:

def numbers = [1, 2, 3, true, 'false']

默认定义的集合对象属于Java.util.ArrayList类,也可以用as运算符,强制定义List接口的其它实现类的对象,例如:

> def list = [1, 2, 3, 4] as LinkedList
> assert list instanceof LinkedList
> def list = [1, 2, 3, 4] as LinkedList
> assert 1 == list[0]
> assert 4 == list[-1]
> list << true
> print list[4]
true

Groovy 可以定义多维集合,例如:

def multi = [[0, 1], [2, 3]]

Groovy中数组和集合的表示方式相同,也就是说Groovy复用list的表示形式来表示数组,但必须显式的声明数组的类型,例如:

> String[] arrStr = ['zhaoshuai-lc', 'zhaoshuai-la', 'zhaoshuai-lb']
> assert arrStr instanceof String[]
> assert !(arrStr instanceof List)

使用as运算符,强制转化为要定义的类型:

> def intArr = [1, 2, 3] as int[]
> assert intArr instanceof int[]

也可以定义多维数组:

> def _matrix = new Integer[2][3]
> assert _matrix.size() == 2

声明时不指定数组元素个数:

> Integer[][] arr
> arr = [[1, 2, 3], [2, 3]]
> print arr.length
2

访问数组元素时按照和list—样的方式,使用下标运算符[],例如:

> String[] strArr = ['zjaosuia', 'dafas', 'erqrw']
> print strArr[2]
erqrw

Java 风格化:

> def primes = new int[]{2, 3, 4, 1, 6}
> assert primes.length == 5 && primes.sum() == 16
> 
> def pets = new String[]{'zhaoshuai', '-', 'lc'}
> assert pets.size() === 3 && pets.sum() == 'zhaoshuai-lc'
> 
> String[] groovyArr = ['zhaoshuaiA', '-A', 'lcA']
> assert groovyArr.every { it -> it.contains('A') }

2.4.1 List 语法详解

groovy 列表使用索引操作符 [] 索引。列表索引从 0 开始,指第一个元素。groovy 中的一个列表中的数据可以是任意类型。这 java 下集合列表有些不同,java 下的列表是同种类型的数据集合。
List.reverse() 可以实现列表反转。
调用 List.sort() 可以实现列表排序。

> def list1 = []
> def list2 = [1, 2, 3, 4]
> list2.add(12)
> list2.add(12)
> println list1.size()
> println list2.size()
0
6

1、搜索-find

class Main {
    static void main(String[] args) {
        def list = [1, 2, 3, 1, 2, 3];
        // find:返回第一个符合条件的项
        def find = list.find( item -> item == 1)
        assert 1 == find

        // findAll:返回所有符合条件的项
        def findA = list.findAll( item -> item == 1)
        assert [1, 1] == findA

        // findIndexOf:返回满足条件的第一个元素的下标值。
        def index = list.findIndexOf(item -> item == 1)
        assert 0 == index
    }
}

2、排序-sort、reverse

class Main {
    static void main(String[] args) {
        def list = [1, 2, 3, 1, 2, 3];
        // sort-正序排序
        print list.sort();
        // sort-倒叙排序
        print list.sort((a, b) -> b - a)
        // reverse:将原list倒序,返回一个新的list
        print list.reverse();
    }
}

3、返回新数组-collect、tail

class Main {
    static void main(String[] args) {
        def list = [1, 2, 3, 1, 2, 3];

        // collect:返回一个新的list,他可以接受一个闭包参数或者无参。类似js中map。it是闭包中自带的隐式变量;
        println list.collect(item -> item + 100)

        // tail:返回一个新的list,它包含list中的所有的元素(除了第一个元素)
        println list.tail(); // [2, 3, 1, 2, 3]
    }
}

4、遍历 each、eachWithIndex

class Main {
    static void main(String[] args) {
        def list = [1, 2, 3, 1, 2, 3];
        // each:普通的迭代遍历
        list.each(item -> print item)

        //eachWithIndex:他的作用和each一样,但是他要传入一个闭包,有两个参数,一个是值,一个是索引。
        list.eachWithIndex { int entry, int i -> println("${entry}--${i}")}
    }
}

every、any、first、last、max、min、count、unique

class Main {
    static void main(String[] args) {
        def list = [1, 2, 3, 1, 2, 3];
        // every:接收一个闭包,返回为一个布尔值,当所有条件都满足时才返回true
        println list.every(item -> item > 0)
        // any:和every用法一样,只要有一个为true,则返回true
        println list.any(item -> item > 0)
        //返回第一个数据
        println(list.first());
        //返回最后一个数据
        println(list.last());
        //返回最大值
        println(list.max());
        //返回最小值
        println(list.min());
        //返回总和
        println(list.sum());
        //返回某项出现的次数
        println(list.count(3));
        //返回去重后的数组
        println(list.unique());
    }
}

5、分组

class Main {
    static void main(String[] args) {
        def items = [[name: "tony", age: 4], [name: "tony", age: 5], [name: "alan", age: 16]]
        def groups = items.groupBy { it.name }
        println(groups);
        // [tony:[[name:tony, age:4], [name:tony, age:5]], alan:[[name:alan, age:16]]]
    }
}

6、包含

class Main {
    static void main(String[] args) {
        def list = [1, 2, 3, 1, 2, 3];
        def list2 = [1, 2, 3, 4];

        println(list.containsAll(list2));
        println(list2.containsAll(list));
    }
}

2.5 Map映射

Groovy的map对象 就是LinkedHashMap的实例
Jenkins pipeline 脚本语言学习支持_第7张图片

class Example { 
   static void main(String[] args) { 
      def mp = ["TopicName" : "Maps", "TopicDescription" : "Methods in Maps"] 
      println(mp.get("TopicName")); 
      println(mp.get("Topic")); 
   } 
}

2.6 对象运算符

安全导航运算符(safe navigation operator) 主要作用为避免出现NullPointerException异常,如果出现空指针异常,使用安全导航运算符将返回null,而不是抛出异常。例如:

> class Person{
>     int id
> 
>     Person(int id) {
>         this.id = id
>     }
> 
>     int getId() {
>         return id
>     }
> 
>     void setId(int id) {
>         this.id = id
>     }
> 
> }
> def person = new Person(3451)
> def _person = person.find{ item -> item.id == 345}
> println _person
> println _person?.id
null
null

直接字段访问运算符(Direct field access operator) 使用该运算符可以不用调用get方法而直接获取字段的值。例如:

> class User {
>     public String name;
>
>     User(String name) {
>         this.name = name;
>     }
>
>     String getName() {
>         "Name: ${name}"
>     }
> }
>
> def user = new User("Bob")
> print user.name
> assert user.name == 'Name: Bob'
Name: Bob

> class User {
>     public String name;
>
>     User(String name) {
>         this.name = name;
>     }
>
>     String getName() {
>         "Name: ${name}"
>     }
> }
>
> def user = new User("Bob")
> print user.@name
> assert user.@name == 'Bob'
Bob

2.7 正则表达式

Groovy使用~”pattern” 来支持正则表达式,它将使用给定的模式字符串创建一个编译好的Java Pattern 对象。Groovy也支持 =~(创建一个Matcher)和 ==~ (返回boolean,是否给定的字符串匹配这个pattern)操作符。

> import java.util.regex.Pattern
>
> def p = ~/foo/
> assert p instanceof Pattern
> def res = p.matcher('foo').matches()
> print res
true
> import java.util.regex.Matcher
>
> def text = 'i am your father'
> def res = text =~ /father/
> assert res instanceof Matcher
> print res.matches()
false
> import java.util.regex.Matcher
>
> def text = 'i am your father'
> def res = text ==~ /father/
> assert res instanceof Boolean
> print res
false

3 类与脚本

Groovy提供了两种代码方式,一种是脚本一种是类,首先我们定义一个名为Main.groovy的类。代码如下:

class Main{
    static void main(String[] args) {
        print 'hello zhaoshuai-lc'
    }
}

print 'hello zhaoshuai-lc'
print 'hello zhaoshuai-lc'

上面的脚本实由groovy.lang.Script类编译成一个class文件,把脚本代码拷贝到groovy.lang.Script类的run方法中进行执行,实际运行的代码形如下面的内容:

Jenkins pipeline 脚本语言学习支持_第8张图片
执行的步骤如下:
Main.class继承Script类
把脚本的主体内容复制到run方法内
然后自动生成main()方法,最后运行run()

方法 可以在脚本中定义方法,例如:

> int fib(int n) {
>     n < 2 ? 1 : fib(n - 1) + fib(n - 2)
> }
>
> assert fib(10) == 89

创建的脚本类在编译后会把脚本中的所有方法装配到run方法中,这些对于用户来说都是透明的。

变量 在脚本中定义变量无需声明变量的类型,例如:

int x = 1
int y = 2
assert x+y == 3
×= 1
y = 2
assert x+y == 3

这两者在语义上有一些差别,上面的例子中声明的变量属于局部变量,只在run方法内部可见,而下面的无声明变量定义对于其它方法可见, 这对于脚本与其它应用程序共享数据就显得很重要了。

Groovy类是数据的集合和对该数据进行操作的方法的载体,类的数据和方法用于表示问题域中的一些现实世界对象。 Groovy中的类声明了该类定义的对象的状态(数据)和行为。因此,Groovy类描述了该类的实例字段和方法。
Jenkins pipeline 脚本语言学习支持_第9张图片
在任何编程语言中,总是使用private关键字隐藏实例成员,通过提供getter和setter方法来相应地设置和获取实例变量的值。例如下面的代码:

Jenkins pipeline 脚本语言学习支持_第10张图片
内部类定义在另一个类中,外层类可以访问内部类,内部类也可以使用外层类的成员变量,即使是私有的。其它类不能访问内部类。内部类的示例如下:

class Main {
    static void main(String[] args) {
        def outer = new Outer()
        outer.name = 'zhaoshuai-lc'
        outer.callInnerMethods()
    }
}

class Outer {
    String name

    def callInnerMethods() {
        new Inner().methodInner()
    }

    class Inner {
        def methodInner() {
            print name
        }
    }
}

extends是用于继承类的关键字,我们通过一个示例介绍groovy中如何继承其它类:

class Main {
    static void main(String[] args) {
        def sub = new Sub('zhaoshuai-lc')
    }
}

class Outer {
    public String name
    Outer(String name) {
        print name
    }
}
class Sub extends Outer {
    Sub(String subName) {
        super(subName)
    }
}

抽象类表示通用概念,因此它不能被实例化,但可以被继承。抽象类中的抽象方法只有方法的定义而没有方法的实现,它的实现通过继承它的类来完成,定义抽象类通过关键字 abstract来声明,抽象方法也是同样的。

接口定义了类需要遵守的规范,接口仅定义需要实现的方法的列表,但是不定义方法实现。 接口需要使用interface关键字声明接口,接口的方法总是公开的,在接口中使用受保护或私有方法是一个错误。

class Example {
   static void main(String[] args) {
      Student st = new Student();
      st.StudentID = 1;
      st.Marks1 = 10;
      println(st.DisplayMarks());
   } 
} 

interface Marks { 
   void DisplayMarks(); 
} 

class Student implements Marks {
   int StudentID
   int Marks1;
	
   void DisplayMarks() {
      println(Marks1);
   }
}

4 闭包

闭包可以接收入参
闭包可以引用外部变量

class Example {     
   static void main(String[] args) {
      def str1 = "Hello";
      def clos = {param -> println "${str1} ${param}"}
      clos.call("World");
		
      // We are now changing the value of the String str1 which is referenced in the closure
      str1 = "Welcome";
      clos.call("World");
   } 
}

//打印
Hello World 
Welcome World

你可能感兴趣的:(Java工具箱,jenkins,学习,运维)