|
|||||||
Материал из Викиучебника
Время создания: 07.06.2019 17:14
Раздел: INFO - Development - GROOVY
Запись: wwwlir/Tetra/master/base/1559484227mm649ry5x9/text.html на raw.githubusercontent.com
|
|||||||
|
|||||||
Материал из Викиучебника — открытых книг для открытого мира П ерейти к навигации Перейти к поиску В Википедии имеется статья по теме «Groovy »
Откройте редактор и напишите программу. По традиции, первая программа должна просто выводить приветствие миру: println "Hello World!" Сохраните её в файл helloworld.groovy и запустите. groovy helloworld.groovy На экране появится надпись: Hello World! На этом традиционную часть можно считать выполненной. Комментарии и демонстрация результата Комментарием называется часть программного кода, пропускаемая при обработке (интерпретации или компиляции). В Groovy знаком начала комментария служит // . Всё, что между ним и концом строки пропускается. Также комментарий можно расположить между / * и */ . Пример: println 2 + 2 // это комментарий println "Привет!" /* это тоже комментарий */ /* А это - многострочный комментарий */ Результат иллюстрируемого кода будет располагаться после последовательности //=>. Пример: println 2 + 2 //=> 4 println "Привет" //=> Привет Переменная в Groovy определяется ключевым словом def (это аналогично типу Object в Java): def a = 1 // объявление "безтиповой" переменной, присвоение ей значения типа int a = "String" /* так как мы не указали тип при объявлении этой переменной, то можно присваивать этой переменной значение другого типа */ int b = 2 // объявление переменной типа int b = "String for type int?" // так как тип переменной указан, // то когда мы пытаемся присвоить String, получаем ошибку (GroovyCastException) В Groovy есть 2 типа строк:
javaString = 'java' // Java String groovyString = "Hello ${javaString}!" // GString println javaString // => java println groovyString // => Hello java! bigGroovyString = """ long long string """ // Длинная строка с отступами def a = "a" println a println a + "12" // конкатенация println a * 3 // умножение Groovy содержит встроенную поддержку списков. Списки объявляются путем перечисления элементов в квадратных скобках: def someList = [1,2,3,4] // Создание списка def emptyList = [] // Создание пустого списка Обращение к элементам списка осуществляется по индексу, как к массиву в Java: someList[0] // Обращение к элементу по индексу Новые элементы могут быть добавлены в список различными способами: someList[5] = 6 // Добавление элемента в список someList << 7 << 8 // Добавление элементов в конец списка
someList += [ 9, 10 ] // "Приклеивание" списка Теперь, совместное использование списков и ranges: someList[1..3] // "Срезка" списка - получение подсписка someList[2..4] = [ 12, 13, 14 ] // Изменение подсписка Также, для индексирования можно использовать и списки: someList[1,3,5..7,9] // Получение подсписка Также, Groovy предоставляет встроенный цикл, для перебора элементов списка, или элементов любого объекта, реализующего интерфейс java.lang.Iterable: for ( e in someList ) { println e // Распечатываем все элементы списка someList } Аналогично спискам, Groovy поддерживает прозрачный синтаксис для работы с maps (ассоциативными массивами). Объявление выглядит следующим образом: def someMap = [ 'a' : 1, 'b' : 2 ] // Объявление Также, существует специальный синтаксис для объявления пустых отображений: // Объявление пустого отображения def emptyMap = [:] def otherEmptyMap = [:] as HashMap Доступ к элементам осуществляется по ключу, с использованием оператора [], или же с ключом как полем: someMap['a'] // Доступ к элементу someMap.a // Доступ к элементу как к полю Аналогично производится и изменение элементов: someMap['a'] = 2 // Изменение элемент someMap.a = 2 // Изменение элемента, как поля Для хранения объектов в качестве ключа можно использовать скобки (): def map = [(new String("username")):"james", nickname:"jcameron", (new Integer(22)):1234] println map.get(new Integer(22)) Одним из наиболее важных особенностей любого языка программирования является возможность выполнять различные коды в разных условиях.Простейший способ сделать это состоит в использовании IF конструкции. Например: def amPM = Calendar.getInstance().get(Calendar.AM_PM) if (amPM == Calendar.AM){ println("Good morning") } else { println("Good evening") } Не беспокойтесь о длинной первой строке, это просто какой-то код, чтобы определить, сейчас утро или вечер. Остальная часть кода выполняется следующим образом: сначала оценивается выражение в круглых скобках и в зависимости от результата true (истинно) или false (ложно) выполняется первый или второй блок кода. Смотрите ниже раздел логические выражения. Обратите внимание, что блок else не требуется, в отличии от первого блока: amPM = Calendar.getInstance().get(Calendar.AM_PM) if (amPM == Calendar.AM){ println("Have another cup of coffee.") } Существует специальный тип данных в большинстве языков программирования, который используется для представления значений истинности,true (истина) и false (ложь). Простейшие логические выражения - это просто слова. Логические значения могут быть сохранены в переменных, как и любой другой тип данных: def myBooleanVariable = true Более сложные логические выражения использует один из булевых операторов:
Большинство из них, довольно интуитивны. Оператор равенства ==, не путайте с оператором присваивания =. Оператор не равенство !=, то есть "не равно". Некоторые примеры: def titanicBoxOffice = 1234600000 def titanicDirector = "James Cameron" def trueLiesBoxOffice = 219000000 def trueLiesDirector = "James Cameron" def returnOfTheKingBoxOffice = 752200000 def returnOfTheKingDirector = "Peter Jackson" def theTwoTowersBoxOffice = 581200000 def theTwoTowersDirector = "PeterJackson" titanicBoxOffice > returnOfTheKingBoxOffice // вычисляется как истина titanicBoxOffice >= returnOfTheKingBoxOffice // вычисляется как истина titanicBoxOffice >= titanicBoxOffice // вычисляется как истина titanicBoxOffice > titanicBoxOffice // оценивается как ложное titanicBoxOffice + trueLiesBoxOffice < returnOfTheKingBoxOffice + theTwoTowersBoxOffice // оценивается как ложное titanicDirector > returnOfTheKingDirector // оценивается как ложное, потому что "J" находится перед "Р" titanicDirector < returnOfTheKingDirector // вычисляется как истина titanicDirector >= "James Cameron" // вычисляется как истина titanicDirector == "James Cameron" // вычисляется как истина Логические выражения особенно полезны при использовании совместно с if-конструкциями. Например: if (titanicBoxOffice + trueLiesBoxOffice > returnOfTheKingBoxOffice + theTwoTowersBoxOffice){ println(titanicDirector + " is a better director than " + returnOfTheKingDirector) } Особенно полезна проверка на наличие значения. К примеру, определён ли данный ключ в карте: def suvMap = ["Acura MDX":"\$36,700", "Ford Explorer":"\$26,845"] if (suvMap["Hummer H3"] != null){ println("A Hummer H3 will set you back "+suvMap["Hummer H3"]); } Вообще null используется для указания на отсутствие значения выражения или переменной. Функции и методы всегда возвращают, как результат, последнее выражение. //класс пользователя class Person{ String first, last } //функции без типизированных параметров def printInfo(first, second){ println "first name: $first, second name: $second" } def printFirstName(user){ println "user: $user.first" } //создаем объект класса Person с параметрами def tempPerson = new Person(first: 'Adam', last: 'Smith') // вызов функции разными способами printInfo tempPerson.first, tempPerson.last printFirstName(tempPerson) printFirstName tempPerson //типизированный параметр def functionA(String str){ println str } functionA 'String'// все ок functionA 1 // вернётся исключение int functionB(int argB) { argB + 2 } String functionC() { "Hello World" } println functionB(1) def hw = functionC() println hw Closure - это замыкание и представляет собой некую анонимную функцию со свойствами объекта. Синтаксис замыкания : { [closureArguments->] statements } def closureFunction = {a, b -> println a println b }
closureFunction(1, 2) В замыканиях по умолчанию присутствует переменная it и ссылается на первый параметр в замыкании: def closureA = { it } assert closureA() == null assert closureA(1) == 1 Вызов замыкания: def c = { it, arg-> println "${it} ${arg}" } c.call("A", "B") // первый тип вызова c("C", "D") // второй тип вызова Определение замыкания в классе и его вызов: public class ClassWithClosure { private int member = 20; private String method() { return "hello"; } def publicMethodWithClosure(String name_) { def localVar = member + 5; def localVar2 = "Parameter: ${name_}";
return { println "${member} ${name_} ${localVar} ${localVar2} ${method()}" } } } ClassWithClosure sample = new ClassWithClosure(); def closureVar = sample.publicMethodWithClosure("Xavier"); closureVar(); Специальный класс Expando для создания динамических объектов и методов (как замыкания) которые можно вызывать: def player = new Expando() player.name = "Alec" player.greeting = { "Hello, my name is $name" } println player.greeting() player.name = "Max" println player.greeting() def out= new File('File1.txt') // если файл не существует, то создаем файл if(!out.exists()) { out.createNewFile() out << 'aaa\nbbb\nccc' // пишем текст в файл } list= [] // создаем список для строк out.eachLine { list<< it } // и заполняем его println list.size() // выводим размер списка строк println out.text // выводим весь текст out.write('\nnew string') // пишем текст в файл out.eachLine { println it} out.append('\nappend string') // добавляем текст в файл //выводим информацию о файле println out.name println out.isAbsolute() println out.path println out.parent println out.absolutePath println out.absoluteFile.toString() println out.canonicalPath println out.canonicalFile.toString() println out.toURI().toString() // Создаем директории def dir= new File('Directory1') dir.mkdir() //make directory, if it doesn't already exist def dir2= new File('Directory2/SubDir1') dir2.mkdirs() lst = /This is my new string./ println lst def b = "abcde" // также строка представляет собой и список символов println b[2] // напечатает c println b[1..3] // напечатает bcd println "reverse me".reverse() println "This is the end, my only friend!".tokenize(' ').reverse().join(' ') Описание и создание класса(по умолчанию класс имеет тип доступа public, а переменные класса имеют тип доступа private, но компилятор groovy сам сделает для этих полей геттеры и сеттеры с доступом public): class Human { String name int age } def man = new Human(); man.name = "Adam" man.age = 25; def woman = new Human(name: "Eva", age: 22 ) Для обновления поля или полей можно использовать такой подход: man.with{ name = "Adam" age = 34 } Классы: // Классы могут не иметь конструктора class ClassWithoutConstructor { } class Bird { static startDate = new Date() private name def getName() { name } def setName(name) { this.name = name } static getStartDate() { startDate } } println Bird.startDate def myBird = new Bird() myBird.name = "Chack" println myBird.name // и иметь разные правила для генерации методов для полей class Cat { def startDate = new Date() // getter и setter final String name = "Empty" final age // только getter Cat(date, name) { startDate = date this.name = name this.age = 1 } } Cat catty = new Cat(new Date(), "Pussy Cat") println catty.name println catty.age println catty.startDate Интерфейсы: // Объявление интерфейса interface Voice{ void voice(); String getAnimalName(); } // его реализация class Dog implements Voice{ @Override void voice() { println "Gav" } @Override String getAnimalName() { return Dog.class.getSimpleName() } void goMethod(){ } } // и использование def dog = new Dog() as Voice // или можно привести к интерфейсу таким способом: def dog = new Dog().asType(Voice.class) dog.voice() println "my name is: " + dog.getAnimalName() // Реализация интерфейса как замыкания def mainRunnable = { run:{ try { int i = 5 while (i>0) { sleep(1000) println "${i--}" } } catch (InterruptedException ex) { // error } } } as Runnable new Thread(mainRunnable).start() Наследование: class PersonA implements Comparable { def firstname, initial, surname PersonA(f,i,s) { firstname = f; initial = i; surname = s } int compareTo(other) { firstname <=> other.firstname } } def a = new PersonA('James', 'T', 'Kirk') def b = new PersonA('Samuel', 'L', 'Jackson') println a <=> b // => -1 class PersonB extends PersonA { PersonB(f,i,s) { super(f,i,s) } int compareTo(other) { initial <=> other.initial } } a = new PersonB('James', 'T', 'Kirk') b = new PersonB('Samuel', 'L', 'Jackson') println a <=> b // => 1 class Parent { private name // my child's name def setChildName(value) { name = value } def getChildName() { name } } class GrandParent extends Parent { private name // my grandchild's name def setgrandChildName(value) { name = value } def getGrandChildName() { name } } g = new GrandParent() g.childName = 'Jason' g.grandChildName = 'Rachel' println g.childName // => Jason println g.grandChildName // => Rachel Абстрактные классы: abstract class Shape { final name Shape(name) { this.name = name } abstract printName() } class Circle extends Shape { final radius Circle(radius) { super('circle') this.radius = radius } def area() { Math.PI * radius * radius } def printName() { println "I am a $name." } } class Rectangle extends Shape { final length, breadth def Rectangle(length, breadth) { super("rectangle") this.length = length this.breadth = breadth } def printName() { println "I am a $name." } } shapes = [new Circle(4.2), new Rectangle(5, 7)] shapes.each { shape -> shape.printName() } Статические внутренние классы: class OuterClass { static class StaticInnerClass { public int getAge(){ int a = 35 } } } OuterClass.StaticInnerClass myInstance = new OuterClass.StaticInnerClass() println myInstance.getAge() Анонимные внутренние классы: new Thread([run: { try { int i = 5 while (i>0) { sleep(1000) println "${i--}" } } catch (InterruptedException ex) { // error } }] as Runnable).start(); Enum: enum Color{ RED, GREEN, BLUE }
def redColor = "RED" as Color Color blueColor = "BLUE" println blueColor Импортируемые пакеты по умолчанию которые добавляются компилятором в каждый сценарий:
Можно импортировать пакеты в статическом контексте, а также назначать алиасы/псевдонимы: import static java.awt.Color.BLUE import static Boolean.FALSE as F // назначаем алиас с именем F import static Calendar.getInstance as now // назначаем алиас с именем now import static java.lang.Integer.* println BLUE // напечатает java.awt.Color[r=0,g=0,b=255] println !F // напечатает true println now().time // напечатает Fri Jun 08 06:37:20 EEST 2011 def a = parseInt("123") println a // напечатает 123 // представление списка как интерфейса Set def contacts = ['a', 'b', 'c'] as Set println contacts.size() // напечатает 3 // представление списка как интерфейса Map def contacts = ['a':10, 'b':20, 'c':30] as Map println contacts['a'] // напечатает 10 // множественное присвоение def (a, b, c) = [1,2,5] println c def (int myint, String mystring) = [5, "hello"] println mystring //диапазоны значений def list = [3, 'Some string' , new Date()] println list[0] println list[1] def letters = 'a'..'z' def numbers = 0..<10 println numbers.size() // работа с замыканиями 3.times { println 'Hi'} [1,2,3].each {it -> println it} (10..1).each {println it} [ 'a' : 1, 'b' : 2 ].each {key, value -> println key} import java.util.GregorianCalendar as D import static java.util.Calendar.getInstance as now println new D(2011, 11, 25).time println now().time println new Date() + 1 dateStr = "2011-06-03" date = Date.parse("yyyy-MM-dd", dateStr) println 'Date was '+date.format("MM/dd/yyyy") // Эта аннотация которая генерирует из данного класса синглетон @Singleton(lazy=true) class MySingleton { def getHello(){ "hello world" } } println MySingleton.instance.hello // Эта аннотация позволяет внедрить в класс Manager поведение метода из класса Employee class Employee { def doWork() { 'my work' } } class Manager { @Delegate Employee slave = new Employee() } def worker = new Manager() println worker.doWork() // либо можно сделать то же самое с помощью mixin class Employee2 { def doWork() { 'my work' } } class Manager2 {} Manager2.mixin Employee2 println new Manager2().doWork() // Аннотация @Immutable делает объект этого класса неизменяемым // свойства объекта становятся readonly @Immutable class Person{ String first, last } Оператор pattern (~) обеспечивает простой способ создать java.util.regex.Pattern. def p = ~/foo/ assert p instanceof Pattern В основном оператор pattern используется со слеш-строками (строки обрамлённых слешами), тем не менее этот оператор может использоваться с любыми видами строк Groovy: p = ~'foo' /*1*/ p = ~"foo" /*2*/ p = ~$/dollar/slashy $ string/$ /*3*/ p = ~"${pattern}" /*4*/
Alternatively to building a pattern, you can directly use the find operator =~ to build a java.util.regex.Matcher instance: def text = "some text to match" def m = text =~ /match/ /*1*/ assert m instanceof Matcher /*2*/ if (!m) { /*3*/ throw new RuntimeException("Oops, text not found!") }
Since a Matcher coerces to a boolean by calling its find method, the =~ operator is consistent with the simple use of Perl’s =~ operator, when it appears as a predicate (in if, while, etc.). The match operator (==~) is a slight variation of the find operator, that does not return a Matcher but a boolean and requires a strict match of the input string: m = text ==~ /match/ /*1*/ assert m instanceof Boolean /*2*/ if (!m) { /*3*/ throw new RuntimeException("Should not reach that point!") }
Подключение к базе данных и запрос SELECT(необходимо подключить драйвер JDBC для MySQL или другой базы): import groovy.sql.Sql Sql sql = Sql.newInstance("jdbc:mysql://localhost:3306/testdatabase", "user", "password", "com.mysql.jdbc.Driver") // создаем таблицу sql.execute('''create table users ( id int(11) not null primary key auto_increment, username varchar(255), age int(11) )''') Выполнение простого sql-запроса Вставка новой записи: def age = 25 def name = "Adam" sql.execute("insert into users (username, age) values (${name}, ${age})") // or sql.executeInsert("insert into users (username, age) values (${name}, ${age})") Выборка первой записи из результата запроса: def rowFirst = sql.firstRow('select username, age from users') println "Row: Name = ${rowFirst.username} and Age = ${rowFirst.age}" Выборка всех записей: sql.eachRow("select * from users"){ row -> println row.username } Удаление записи: int id = 2 sql.execute('delete from users where id = ?' , [id]) Обновление записи: def newUsername = 'New Name' int rowsAffected = sql.executeUpdate('update users set username = ? where id=2', [newUsername]) println "updated: ${rowsAffected}"; Выполнение более сложных запросов import groovy.sql.Sql import groovy.sql.DataSet DataSet users Sql sql = Sql.newInstance("jdbc:mysql://localhost:3306/testdatabase", "user", "password", "com.mysql.jdbc.Driver") // таблица users должна быть создана users = sql.dataSet("USERS") users.add(username: "James", age: 55) //вставка новой записи в таблицу DataSet findedUsers = users.findAll() // получение всех записей и их вывод findedUsers.each{ println it.username} Добавление записей в транзакции: import groovy.sql.Sql DataSet users Sql sql = Sql.newInstance("jdbc:mysql://localhost:3306/testdatabase", "user", "password", "com.mysql.jdbc.Driver") // таблица users должна быть создана users = sql.dataSet("USERS") sql.withTransaction { users.add(username: "Alec", age: 25) users.add(username: "Alec 2", age: 25) } Блочное добавление записей: import groovy.sql.Sql Sql sql = Sql.newInstance("jdbc:mysql://localhost:3306/testdatabase", "user", "password", "com.mysql.jdbc.Driver") def updateCounts = sql.withBatch('insert into users(username, age) values (?, ?)') { ps -> ps.addBatch("New Name", 22) // varargs style ps.addBatch(["New Name", 18]) // list ps.addBatch(["New Name", 31]) } Вызов процедур: import groovy.sql.Sql Sql sql = Sql.newInstance("jdbc:mysql://localhost:3306/testdatabase", "user", "password", "com.mysql.jdbc.Driver") sql.call("{? = call MyProcedure(?)}", [Sql.VARCHAR, 'Sam']) { name -> assert name == 'Adam' } // or with GString def first = 'Sam' sql.call("{$Sql.VARCHAR = call MyProcedure($first)}") { name -> assert name == 'Adam' } import groovy.json.JsonBuilder import groovy.json.JsonSlurper import groovy.json.JsonOutput // Создание JSON объекта def json = new JsonBuilder() json.person { username "Guillaume" age 33 pets "Hector", "Felix" } println json.toString() // вывод в строку полученного объекта // Парсинг строки в JSON формате def someJSONString = '{"person":{"username":"Guillaume","age":33,"pets":["Hector","Felix"]}}' println JsonOutput.prettyPrint(someJSONString) // форматированный вывод объекта def slurper = new JsonSlurper() def doc = slurper.parseText(someJSONString) println doc.person.username // вывод имени doc.person.pets.each {println it} // вывод животных Создание XML документа из объекта: import groovy.xml.MarkupBuilder writer = new StringWriter() builder = new MarkupBuilder(writer) petsList = [ "Hector", "Felix"] builder.person() { username("Guillaume") age("33") gender("female") pets(){ for (e in petsList){pet(e)} } } println writer.toString() Работа с HTML: import groovy.xml.MarkupBuilder def writer = new StringWriter() def builder = new MarkupBuilder(writer) builder.html() { head() { title("This is the title") } body() { div("class" : "main") { p("this is the body") } } } println writer.toString() Парсинг XML документа def xmlString = """ <person> <username>Guillaume</username> <age>33</age> <gender>female</gender> <pets> <pet>Hector</pet> <pet>Felix</pet> </pets> </person> """ def person = new XmlSlurper().parseText(xmlString) println person.username person.pets.pet.each {println "pet's name:"+it} //эта аннотация скачивает и устанавливает библиотеку в classpath @Grab(group='org.codehaus.gpars', module='gpars', version='0.12') import static groovyx.gpars.GParsExecutorsPool.withPool //запуск в новом потоке Thread.start { println Thread.currentThread().getId() } //50 раз сделать асинхронную загрузку страницы(и распечатать ответ) //по url в отдельных потоках int count = 50 withPool(count) { count.times { Closure callUrl = {"http://google.com".toURL().withReader { reader -> println reader.readLines() }} callUrl.callAsync();
} }
Править ссылки
|
|||||||
Так же в этом разделе:
|
|||||||
|
|||||||
|