Перейти к основному содержимому

Справочник по языку Groovy


Справочник-шпаргалка по Groovy — типы, синтаксис, стандартная библиотека, типовые паттерны. Не заменяет пошаговое обучение. Учебный курс: раздел.

Учебные статьи: Типы данных.

Groovy — Java-подобный язык для JVM с динамической и статической типизацией, встроенными литералами коллекций, регулярных выражений и замыканиями (появились в Groovy раньше, чем лямбды в Java). Компиляция в байт-код; стандарт — JSR 241; разработка под эгидой Apache (Apache License 2.0). Расширения файлов — .groovy, .gvy, .gsh, .gy.

Компоненты и ключевые особенности языка — в разделах ниже.


Справочные таблицы​

Содержание справочника​


1. Типы данных​

Простые типы​

  • null — отсутствие значения.
  • boolean — логическое значение: true, false.
  • char — одиночный символ в одинарных кавычках: 'A'.
  • int, long, BigInteger — целочисленные типы.
  • float, double, BigDecimal — числа с плавающей точкой.

Строки​

  • GString ("...") — интерполируемая строка, поддерживает выражения ${выражение}.
  • String ('...') — обычная строка без интерполяции.
  • Triple-quoted string ('''...''') — многострочная строка без интерполяции.
  • Slashy string (/.../) — удобна для регулярных выражений, не требует экранирования слешей.
  • Dollar-slashy string ($/.../$) — многострочная строка с интерполяцией и минимальным экранированием.

Коллекции​

  • List — упорядоченный список, изменяемый по умолчанию:
def list = [1, 2, 3]
  • Set — множество уникальных элементов:
def set = [1, 2, 3] as Set
  • Map — ассоциативный массив:
def map = [name: 'Alice', age: 30]

Диапазоны (Ranges)​

  • Используются для перебора значений:
def range = 1..5 // включительно
def exclusive = 1..<5 // исключительно

Файлы и ресурсы​

  • Объект File используется напрямую из Java.
  • Groovy добавляет методы вроде eachLine, splitEachLine, withReader.

2. Операторы​

Арифметические​

  • +, -, *, /, %, ** (возведение в степень)

Логические​

  • &&, ||, !

Побитовые​

  • &, |, ^, ~, <<, >>, >>>

Операторы сравнения​

  • ==, !=, <, <=, >, >=
  • Groovy переопределяет == как вызов .equals(), а не сравнение ссылок.

Операторы присваивания​

  • =, +=, -=, *=, /=, %=, **=, &=, |=, ^=, <<=, >>=, >>>=

Операторы безопасной навигации​

Проверка существования ссылки перед доступом — см. Проверка и валидация.

  • ?. — вызов метода или доступ к свойству только если объект не null:
person?.address?.city

Оператор Elvis​

  • ?: — возвращает левый операнд, если он не null и не false; иначе — правый:
name = providedName ?: 'Anonymous'

Оператор распространения (Spread operator)​

  • *. — применяет метод ко всем элементам коллекции:
names*.toUpperCase()

Оператор объединения списков​

  • + — объединяет списки или карты.
  • - — удаляет элементы из списка или ключи из карты.

Оператор индексации​

  • [] — доступ к элементу по индексу или ключу:
list[0], map['key'], map.key

Оператор диапазона​

  • .., ..<

Оператор замыкания​

  • { параметры -> тело }

3. Управляющие конструкции​

Условные операторы​

  • if / else if / else
  • switch / case — поддерживает сопоставление с любыми типами, включая классы, регулярные выражения, замыкания.

Циклы​

  • for (i in collection) — итерация по коллекции, диапазону, массиву.
  • while (condition) { ... }
  • loop.each { item -> ... } — функциональный стиль через замыкания.

Обработка исключений​

  • try / catch / finally — стандартный механизм Java, полностью поддерживается.

4. Методы и функции​

Объявление​

  • Методы объявляются с помощью ключевого слова def или явного типа возврата:
def greet(name) { "Hello, $name!" }
String greet(String name) { "Hello, $name!" }

Необязательные параметры​

  • Поддерживаются значения по умолчанию:
def log(message, level = 'INFO') { ... }

Переменное число аргументов​

  • Используется оператор ...:
def sum(int... numbers) { numbers.sum() }

Явный возврат​

  • Последнее выражение в методе автоматически возвращается, но можно использовать return.

5. Классы и объекты​

Объявление класса​

class Person {
String name
int age

String toString() { "$name ($age)" }
}

Автоматические геттеры и сеттеры​

  • Все поля получают геттеры и сеттеры по соглашению.

Конструкторы​

  • Конструктор по умолчанию принимает Map:
def p = new Person(name: 'Bob', age: 25)

Наследование​

  • Поддерживается через extends.

Интерфейсы и трейты​

  • Интерфейсы работают как в Java.
  • Traits — мощный механизм повторного использования кода:
trait Flyable { void fly() { println "Flying!" } }
class Bird implements Flyable { }

Аннотации​

  • Поддерживаются все Java-аннотации.
  • Groovy предоставляет собственные аннотации — @CompileStatic, @TypeChecked, @Delegate, @Lazy, @Immutable, @Sortable, @Canonical, и другие.

6. Замыкания (Closures)​

Синтаксис​

{ param1, param2 -> body }

Неявные параметры​

  • it — имя по умолчанию для единственного параметра:
[1, 2, 3].each { println it }

Делегирование​

closure.delegate = someObject
closure.resolveStrategy = Closure.DELEGATE_FIRST

Полезные методы для замыканий​

  • , curry(), rcurry(), memoize(), trampoline()
call()

7. Коллекции и их методы​

List (упорядоченный список)​

ДействиеМетод / синтаксис
Добавить в конецadd(value), leftShift(value) (<<)
Вставить по индексуadd(index, value)
Прочитатьget(index), list[index]
ЗаменитьputAt(index, value), list[index] = value
Удалить по индексуremove(index)

Плюс — each, collect, findAll, sort, reverse, unique, flatten, sum, min, max.


Map (словарь)​

ДействиеМетод / синтаксис
Записатьput(key, value), map[key] = value
Прочитатьget(key), map[key]
Удалитьremove(key)

Плюс — keySet(), values(), entrySet(), each, collectEntries, subMap.


Set (множество)​

ДействиеМетод
Добавитьadd(value), leftShift(value)
Удалитьremove(value)
Проверитьcontains(value)

String​

  • eachMatch(regex), tokenize(), padLeft(), padRight(), toInteger(), toDouble(), replaceAll(), eachLine()

8. Метапрограммирование​

Runtime metaprogramming​

  • Добавление методов и свойств во время выполнения:
Person.metaClass.greet = { -> "Hi from $name" }

ExpandoMetaClass​

  • Включается глобально или для конкретного класса.

methodMissing / propertyMissing​

  • Перехват вызовов несуществующих методов или свойств.

invokeMethod​

  • Перехват всех вызовов методов объекта.

Categories​

  • Временное расширение поведения классов в блоке use.

AST Transformations (compile-time)​

  • Изменяют дерево абстрактного синтаксиса на этапе компиляции.
  • Примеры — @ToString, @EqualsAndHashCode, @TupleConstructor, @Bindable, @ListenerList

9. Компиляция и настройки​

Режимы компиляции​

  • Dynamic — поведение по умолчанию, проверка типов во время выполнения.
  • Static compilation — через @CompileStatic, обеспечивает производительность как у Java.
  • Type checking — через @TypeChecked, проверяет типы, но оставляет динамическое поведение.

Параметры компилятора Groovy​

  • indy — использование invokedynamic (JDK 7+).
  • encoding — кодировка исходного файла.
  • targetBytecode — версия байткода (например, 1.8, 11, 17).
  • parameters — сохранение имён параметров в байткоде.
  • previewFeatures — включение preview-функций JDK.

Конфигурация через groovyOptions​

В Gradle:

compileGroovy {
groovyOptions.optimizationOptions.indy = true
groovyOptions.configurationScript = file('config.groovy')
}

10. Интеграция с Java​

  • Любой Java-класс доступен напрямую.
  • Groovy-классы компилируются в байткод JVM и могут использоваться из Java.
  • Совместимость с Java Collections API, Streams, Optional и другими конструкциями.

11. DSL и скриптование​

GroovyShell​

  • Выполнение строк как кода:
new GroovyShell().evaluate('2 + 3')

GroovyScriptEngine​

  • Загрузка и выполнение скриптов из файлов.

Builder-паттерн​

  • Встроенные MarkupBuilder, JsonBuilder, StreamingJsonBuilder, ObjectGraphBuilder.

Пример:

def builder = new MarkupBuilder()
builder.person {
name 'Alice'
age 30
}

12. Распространённые утилиты и расширения​

Расширения для чисел​

  • times { ... } — повторить действие N раз.
  • upto(to) { ... }, downto(to) { ... }

Расширения для файлов​

  • eachFile, eachDir, deleteDir(), getText(), write(text)

Расширения для потоков​

  • withStream { ... }, withWriter { ... }

Расширения для дат​

  • Date.plus(days), Date.minus(days), parse(format, string)

13. Безопасность и ограничения​

  • При выполнении внешних скриптов используйте SecureASTCustomizer для ограничения доступа к опасным API.
  • Отключите возможность создания новых классов, вызова System.exit, доступа к файловой системе и т.п.

Пример:

def secure = new SecureASTCustomizer()
secure.closuresAllowed = false
secure.methodDefinitionAllowed = false

14. AST-трансформации (Compile-time Metaprogramming)​

Groovy позволяет изменять структуру кода на этапе компиляции через аннотации, которые преобразуют абстрактное синтаксическое дерево (AST). Это мощный механизм для генерации кода без рантайм-накладных расходов.


Встроенные AST-трансформации​

@Canonical​

Объединяет @ToString, @EqualsAndHashCode, @TupleConstructor:

@Canonical
class Person {
String name
int age
}

@ToString​

Генерирует метод toString():

@ToString(includeNames = true, includePackage = false)
class Point { int x, y }
// Результат: Point(x:10, y:20)

Параметры:

  • includeNames — добавлять имена полей.
  • includePackage — включать имя пакета.
  • excludes — исключить поля.
  • includes — включить только указанные поля.

@EqualsAndHashCode​

Генерирует equals() и hashCode().


@TupleConstructor​

Создаёт конструктор на основе полей:

@TupleConstructor
class Point { int x, y }
def p = new Point(1, 2)

@Immutable​

Делает класс неизменяемым:

  • Все поля становятся final.
  • Генерируются геттеры.
  • Коллекции оборачиваются в неизменяемые обёртки.
  • Класс объявляется final.

@Sortable​

Добавляет реализацию Comparable и статические методы comparatorBy*.


@Delegate​

Делегирует вызовы методов другому объекту:

class Engine {
void start() { println "Engine started" }
}

class Car {
@Delegate Engine engine = new Engine()
}
new Car().start() // вызывает engine.start()

@Lazy​

Ленивая инициализация поля:

class Heavy {
@Lazy def resource = { /* expensive init */ }()
}

@Synchronized​

Автоматически оборачивает метод в synchronized.


@Field​

Превращает переменную в поле класса (в скриптах):

@Field String name = 'Alice'

@PackageScope​

Делает член класса доступным только в пределах пакета.


@Bindable и @Vetoable​

Используются в GUI-приложениях для поддержки property change listeners.


15. Расширенное метапрограммирование​

ExpandoMetaClass​

Позволяет динамически добавлять методы, свойства, статические методы:

String.metaClass.shout = { -> delegate.toUpperCase() + '!' }
println "hello".shout() // HELLO!

Включение глобально:

ExpandoMetaClass.enableGlobally()

methodMissing и propertyMissing​

Перехват несуществующих вызовов:

class Dynamic {
def methodMissing(String name, args) {
return "Called $name with ${args.join(', ')}"
}
}

invokeMethod​

Перехват всех вызовов методов (включая существующие, если metaClass.invokeMethod переопределён).


getProperty / setProperty​

Контроль доступа к свойствам.


Categories​

Временное расширение поведения:

class NumberUtils {
static double square(Number n) { n * n }
}

use(NumberUtils) {
println 5.square() // 25.0
}

16. Работа с данными​

JSON​

Чтение​
def json = new JsonSlurper().parseText('{"name":"Alice"}')
println json.name

Запись​
def builder = new JsonBuilder()
builder.person {
name 'Alice'
age 30
}
println builder.toPrettyString()

StreamingJsonBuilder​

Для больших объёмов данных:

def writer = new StringWriter()
def builder = new StreamingJsonBuilder(writer)
builder.people {
person { name 'Alice' }
}

XML​

Parsing​
def xml = '''
<books>
<book title="Groovy Guide"/>
</books>
'''
def data = new XmlSlurper().parseText(xml)
println data.book[0].@title

Построение​
def builder = new MarkupBuilder()
builder.books {
book(title: 'Groovy Guide')
}

XPath-подобные запросы​
data.book.findAll { it.@year.toInteger() > 2020 }

17. Шаблоны​

SimpleTemplateEngine​

Поддерживает ${выражения}:

def engine = new SimpleTemplateEngine()
def template = engine.createTemplate('Hello, $name!')
def result = template.make(name: 'Alice')

GStringTemplateEngine​

Более мощный, поддерживает логику внутри шаблона.


XmlTemplateEngine​

Для генерации XML с логикой.


18. Интеграция с Gradle​

Groovy — основной язык написания скриптов сборки в Gradle (до появления Kotlin DSL).

Пример build.gradle:

plugins {
id 'groovy'
}

repositories {
mavenCentral()
}

dependencies {
implementation 'org.apache.groovy:groovy:4.0.15'
testImplementation 'org.spockframework:spock-core:2.3-groovy-4.0'
}

Кастомные задачи на Groovy​

task hello {
doLast {
println "Hello from Groovy in Gradle!"
}
}

Конфигурация компилятора​

compileGroovy {
groovyOptions.optimizationOptions.indy = true
groovyOptions.targetBytecode = '17'
}

19. Тестирование — Spock Framework​

Spock — BDD-фреймворк на Groovy, сочетающий выразительность и мощь.


Структура спецификации​

class MathSpec extends Specification {
def "sum of two numbers"() {
expect:
a + b == c

where:
a | b || c
1 | 2 || 3
4 | 5 || 9
}
}

Блоки​

  • given — подготовка
  • when — действие
  • then — проверка
  • expect — комбинация when/then
  • where — параметризация
  • cleanup — завершение
  • setup — аналог @Before

Моки и спайки​

def service = Mock(Service)
service.process(_) >> "OK"

20. Производительность и оптимизация​

Статическая компиляция​

Используйте @CompileStatic для критичных к производительности участков:

@CompileStatic
int factorial(int n) {
n <= 1 ? 1 : n * factorial(n - 1)
}

Избегайте динамических вызовов в циклах​

Кэшируйте методы или используйте интерфейсы.


Используйте @TypeChecked для поиска ошибок​

Проверяет типы, но сохраняет динамические возможности при необходимости.


invokedynamic (indy)​

Включите флаг -indy при компиляции для ускорения вызовов замыканий и динамических методов (требует JDK 7+).


Профилирование​

Используйте VisualVM, JProfiler или async-profiler для анализа узких мест.


21. Практическое применение Groovy​

Скрипты автоматизации​

  • Обработка логов
  • Генерация конфигураций
  • Миграции данных

DSL для конфигурации​

server {
port 8080
host 'localhost'
ssl enabled: true
}

Jenkins Pipelines​

Declarative и Scripted Pipelines на Groovy.


Тестовые фреймворки​

  • Spock
  • Geb (для UI-тестов)

Встраивание в Java-приложения​

  • Через GroovyShell
  • Через GroovyScriptEngine для горячей замены логики

22. Версии и совместимость​

  • Groovy 2.x — поддержка JDK 6–8, начало AST-трансформаций.
  • Groovy 3.x — поддержка Java 8+, новые операторы (!in, !instanceof), улучшенная совместимость с Java.
  • Groovy 4.x — поддержка JDK 17, улучшенная статическая компиляция, модульность, Jakarta EE.

Рекомендуется использовать Groovy 4.0+ для новых проектов.


23. Ограничения и предостережения​

  • Динамическая природа снижает производительность по сравнению с Java.
  • Отладка динамического кода сложнее.
  • Некоторые IDE хуже поддерживают Groovy, чем Java.
  • При смешивании с Java возможны неочевидные ошибки из-за различий в семантике ==, in, [].

24. Встроенные методы расширений (GDK — Groovy Development Kit)​

Groovy автоматически добавляет сотни полезных методов к стандартным классам Java через механизм метаклассов. Эти методы определены в классах:

  • DefaultGroovyMethods — для большинства объектов
  • DefaultGroovyStaticMethods — статические методы
  • StringGroovyMethods, FileGroovyMethods, IOGroovyMethods, SqlGroovyMethods и др.

Эти методы доступны везде, без импорта.


Общие методы для коллекций​

each​
[1, 2, 3].each { println it }

collect​

Преобразует каждый элемент:

[1, 2, 3].collect { it * 2 } // [2, 4, 6]

findAll / grep​

Фильтрация:

[1, 2, 3, 4].findAll { it % 2 == 0 } // [2, 4]
['a1', 'b2', 'c3'].grep(~/\d$/) // строки, оканчивающиеся цифрой

any / every​

Проверка условий:

[1, 2, 3].any { it > 2 } // true
[1, 2, 3].every { it > 0 } // true

groupBy​

Группировка:

['apple', 'banana', 'cherry'].groupBy { it[0] }
// [a:['apple'], b:['banana'], c:['cherry']]

sum, min, max​
[1, 2, 3].sum() // 6
[1, 2, 3].max() // 3

inject (аналог reduce)​
[1, 2, 3].inject(0) { acc, val -> acc + val } // 6

flatten​

Разворачивает вложенные коллекции:

[[1, 2], [3, 4]].flatten() // [1, 2, 3, 4]

unique​

Удаляет дубликаты:

[1, 2, 2, 3].unique() // [1, 2, 3]

sort​

Сортировка:

[3, 1, 2].sort() // [1, 2, 3]
people.sort { it.age }

reverse​

Инверсия порядка.


pop, push, shift, unshift​

Для работы как со стеком или очередью:

def stack = [1, 2, 3]
stack.push(4) // [1, 2, 3, 4]
stack.pop() // 4

Примечание: push/pop работают с концом списка, shift/unshift — с началом.


Методы для строк​

toInteger(), toDouble(), toBoolean()​

Безопасное преобразование:

'123'.toInteger() // 123
'false'.toBoolean() // false

padLeft(), padRight()​
'5'.padLeft(3, '0') // '005'

tokenize()​

Разделение без регулярных выражений:

'a,b,c'.tokenize(',') // ['a', 'b', 'c']

eachMatch(regex)​

Итерация по совпадениям:

'abc123def456'.eachMatch(/\d+/) { match -> println match[0] }
// 123
// 456

contains(), startsWith(), endsWith() — уже есть в Java, но Groovy делает их null-safe.​

Методы для файлов и потоков​

eachLine​
new File('data.txt').eachLine { line -> println line }

splitEachLine​
file.splitEachLine(/\t/) { parts -> println parts[0] }

withReader, withWriter, withInputStream, withOutputStream​

Автоматическое закрытие ресурсов:

file.withReader { reader -> ... }

getText(), write(text), append(text)​
def content = file.getText('UTF-8')
file.write('Hello', 'UTF-8')

eachFile, eachDir, traverse​

Рекурсивный обход:

dir.traverse { file -> if (file.name.endsWith('.groovy')) println file }

deleteDir()​

Рекурсивное удаление каталога.


Методы для чисел​

times​
5.times { println 'Hello' }

upto, downto​
1.upto(3) { println it } // 1, 2, 3
5.downto(3) { println it } // 5, 4, 3

step​
0.step(10, 2) { println it } // 0, 2, 4, 6, 8

Методы для карт (Map)​

get(key, defaultValue)​
map.get('name', 'Unknown')

subMap(keys)​
map.subMap(['name', 'age'])

collectEntries​

Преобразование в новую карту:

[1, 2, 3].collectEntries { [it, it * it] } // [1:1, 2:4, 3:9]

each, eachWithIndex​
map.each { key, value -> println "$key = $value" }

25. Регулярные выражения​

Groovy упрощает работу с регулярками.


Создание​

  • Используйте slashy strings (/.../) — не нужно экранировать \:
def pattern = /\d{3}-\d{2}-\d{4}/

Сопоставление​

  • Оператор ==~ — полное совпадение:
'123-45-6789' ==~ /\d{3}-\d{2}-\d{4}/ // true
  • Оператор =~ — частичное совпадение, возвращает java.util.regex.Matcher:
def matcher = 'ID: 123' =~ /(\d+)/
if (matcher) {
println matcher[0][1] // '123'
}

Замена​

'Price: $100'.replaceFirst(/\$(\d+)/) { all, amount -> "€${amount}" }
// Price: €100

Группы​

def m = 'John Doe' =~ /(\w+) (\w+)/
if (m) {
def (full, first, last) = m[0]
println "First: $first, Last: $last"
}

26. Многопоточность и параллелизм​

GPars (Groovy Parallel Systems)​

Хотя GPars больше не активно развивается, его идеи повлияли на современные подходы. В Groovy 4+ рекомендуется использовать Java concurrency utilities, но с Groovy-синтаксисом.


Пример с ExecutorService​
def service = Executors.newFixedThreadPool(4)
def futures = (1..10).collect {
service.submit { it * it }
}
futures*.get().each { println it }
service.shutdown()

Параллельная обработка коллекций​
def results = [1, 2, 3, 4].parallelStream().map { it * 2 }.toList()

Groovy не добавляет собственных примитивов для async/await, но легко интегрируется с CompletableFuture:

def future = CompletableFuture.supplyAsync { 42 }
future.thenAccept { println it }.join()

27. Управление ресурсами и замыкания​

Groovy поощряет использование замыканий для управления жизненным циклом:

new File('input.txt').withReader { reader ->
new File('output.txt').withWriter { writer ->
reader.eachLine { line ->
writer.println line.toUpperCase()
}
}
}

Аналогично для:

  • Баз данных (Sql.withInstance)
  • HTTP-соединений
  • ZIP-архивов
  • Сокетов

Это гарантирует вызов close(), даже при исключении.


28. Практические паттерны использования​

1. Конфигурационные файлы​

config.groovy:

server {
port = 8080
ssl = true
hosts = ['localhost', '127.0.0.1']
}

Загрузка:

def config = new ConfigSlurper().parse(new File('config.groovy').toURL())
println config.server.port

2. ETL-скрипты​

new File('input.csv').splitEachLine(',') { fields ->
def record = [id: fields[0], name: fields[1]]
if (record.name) db.insert(record)
}

3. Генерация кода​

def template = '''
class ${className} {
${fields.collect { "String $it" }.join('\n ')}
}
'''
def engine = new SimpleTemplateEngine()
println engine.createTemplate(template).make(className: 'User', fields: ['name', 'email'])

4. Административные скрипты​

  • Очистка логов
  • Архивирование
  • Мониторинг

5. Jenkins Shared Libraries​

DSL на Groovy для стандартизации CI/CD. Подробный разбор: Jenkins Shared Library. Создание jobs — Job DSL Playground.


29. Инструменты и экосистема​

ИнструментНазначение
Groovy ConsoleИнтерактивная среда выполнения
GroovyShellREPL для экспериментов
GradleСборка и управление зависимостями
SpockТестирование
GebUI-тестирование (Selenium + jQuery-подобный синтаксис)
RatpackЛёгкий фреймворк для веб-API
GrailsFull-stack веб-фреймворк (на базе Spring Boot)
GriffonНастольные приложения (JavaFX/Swing)

Среды разработки​

Groovy поддерживают основные IDE:

IDEПоддержка
IntelliJ IDEAВстроенная (с версии 7); для старых версий — плагин JetGroovy
EclipseПлагин Groovy-Eclipse
NetBeansВстроенная
VS CodeРасширение Groovy
VimРасширения сообщества

Файлы и ресурсы​


30. Советы по стилю и читаемости​

  • Используйте def только когда тип не важен или выводится.
  • Предпочитайте @CompileStatic в производственном коде.
  • Избегайте глобального метапрограммирования в больших проектах.
  • Используйте ConfigSlurper вместо Properties.
  • Пишите DSL с Closure.DELEGATE_FIRST.
  • Для скриптов — минимум зависимостей, максимум автономности.

31. Структура типичного Groovy-проекта​

Groovy не навязывает жёсткой структуры, но следует общепринятым соглашениям JVM-экосистемы, особенно если используется Gradle или Maven.


Минимальная структура (скриптовый проект)​

my-groovy-project/
├── scripts/
│ ├── deploy.groovy
│ └── backup.groovy
├── lib/
│ └── helpers.groovy
├── config/
│ └── app.groovy
└── README.md

Стандартная структура (Gradle-проект)​

src/
├── main/
│ ├── groovy/ # основной код
│ └── resources/ # конфиги, шаблоны, данные
└── test/
├── groovy/ # тесты (Spock, JUnit)
└── resources/ # тестовые ресурсы
build.gradle
gradle.properties
settings.gradle

Модульный проект (несколько подпроектов)​

project-root/
├── core/ # ядро: DSL, утилиты
├── cli/ # командная оболочка
├── web/ # веб-интерфейс (Ratpack/Grails)
├── scripts/ # автономные скрипты
└── build.gradle # корневой билд-файл

Важно: Groovy-файлы могут содержать как классы, так и свободные выражения (скрипты). Файл с class компилируется в .class, файл без — в наследника groovy.lang.Script.


32. Организация кода​

Классы и Скрипты​

  • Классы — для переиспользуемой логики, библиотек, компонентов.
  • Скрипты — для автоматизации, одноразовых задач, точек входа.

Пример скрипта (hello.groovy):

println "Hello from script!"
def name = args[0] ?: 'World'
println "Hi, $name!"

Запуск:

groovy hello.groovy Alice

Пакеты и импорты​

  • Используются так же, как в Java.
  • Groovy позволяет опускать package в скриптах, но рекомендуется указывать в библиотеках.

Разделение ответственности​

  • DSL-слои — декларативное описание.
  • Интерпретаторы — преобразование DSL в действия.
  • Инфраструктурные утилиты — работа с файлами, сетью, БД.

33. Управление зависимостями​

Через Gradle​

dependencies {
implementation 'org.apache.groovy:groovy:4.0.15'
implementation 'org.apache.commons:commons-text:1.10.0'
testImplementation 'org.spockframework:spock-core:2.3-groovy-4.0'
}

Через @Grab (в скриптах)​

@Grab('org.apache.commons:commons-text:1.10.0')

import org.apache.commons.text.WordUtils

println WordUtils.capitalize('hello world')

Предупреждение: @Grab использует Ivy под капотом, может быть медленным и ненадёжным в изолированных средах. В продакшене предпочтительнее Gradle/Maven.


34. Конфигурация приложения​

ConfigSlurper​

Читает .groovy-файлы как конфигурацию:

// config/app.groovy
environments {
development {
db.url = 'jdbc:h2:mem:dev'
}
production {
db.url = 'jdbc:postgresql://prod/db'
}
}

Загрузка:

def env = System.getenv('ENV') ?: 'development'
def config = new ConfigSlurper(env).parse(new File('config/app.groovy').toURL())
println config.db.url

Поддержка иерархии​

  • Возможны вложенные блоки.
  • Поддержка include через ConfigObject.merge().

Альтернативы​

  • JSON/YAML через JsonSlurper / YamlSlurper (из SnakeYAML).
  • Properties — через Properties.

35. Настройка компилятора Groovy​

Параметры компиляции (через CLI)​

groovyc -j -indy -targetBytecode 17 src/*.groovy

Флаги:

  • -j — совместная компиляция Java + Groovy
  • -indy — использовать invokedynamic
  • -targetBytecode — версия JVM
  • -encoding UTF-8

Через Gradle​

compileGroovy {
groovyOptions.optimizationOptions.indy = true
groovyOptions.encoding = 'UTF-8'
groovyOptions.targetBytecode = '17'
}

Custom Compilation Configuration​

Можно создать groovyCompiler.groovy:

withConfig(configuration) {
ast(groovy.transform.CompileStatic)
}

И подключить:

compileGroovy {
groovyOptions.configurationScript = file('groovyCompiler.groovy')
}

36. Обработка ошибок и логирование​

Исключения​

  • Используются стандартные Java-механизмы.
  • Groovy не требует объявления throws.

Логирование​

Рекомендуется SLF4J:

@Grab('org.slf4j:slf4j-simple:2.0.7')

import org.slf4j.LoggerFactory

def log = LoggerFactory.getLogger(this.class)
log.info("Processing item")

Или встроенное логирование через java.util.logging:

def logger = java.util.logging.Logger.getLogger('MyApp')
logger.info('Started')

37. Тестирование и проверка качества​

Spock — основной выбор​

  • Человекочитаемые спецификации.
  • Встроенные моки.
  • Параметризованные тесты.

Покрытие кода​

  • JaCoCo через Gradle:
plugins { id 'jacoco' }
jacocoTestReport {
reports {
html.required = true
xml.required = false
}
}

Статический анализ​

  • CodeNarc — линтер для Groovy:
plugins { id 'codenarc' }
codenarcMain {
configFile = file('config/codenarc.groovy')
}

Пример codenarc.groovy:

ruleset {
ruleset('rulesets/basic.xml')
ruleset('rulesets/braces.xml')
ruleset('rulesets/naming.xml')
}

38. Запуск и развёртывание​

Самодостаточный JAR (fat jar)​

jar {
manifest {
attributes 'Main-Class': 'MyApp'
}
duplicatesStrategy = DuplicatesStrategy.EXCLUDE
from { configurations.runtimeClasspath.collect { it.isDirectory() ? it : zipTree(it) } }
}

Скрипты как исполняемые файлы (Unix)​

#!/usr/bin/env groovy
println "Running as script"

Убедитесь, что groovy в PATH.


Docker-образ​

FROM openjdk:17-jdk-slim
COPY build/libs/app.jar /app.jar
CMD ["java", "-jar", "/app.jar"]

39. Безопасность при выполнении скриптов​

Если вы выполняете внешние Groovy-скрипты (например, от пользователей), обязательно ограничьте окружение:


SecureASTCustomizer​

def secure = new SecureASTCustomizer()
secure.closuresAllowed = false
secure.methodDefinitionAllowed = false
secure.importsWhitelist = ['java.lang.String']
secure.starImportsWhitelist = []
secure.staticImportsWhitelist = []
secure.tokensBlacklist = [TokenConstants.ASSIGN, TokenConstants.PLUS_PLUS]

def compiler = new CompilerConfiguration()
compiler.addCompilationCustomizers(secure)

def shell = new GroovyShell(this.class.classLoader, new Binding(), compiler)
shell.evaluate(untrustedCode)

Ограничение доступа к файловой системе, сети, рефлексии.​


40. Профилирование и отладка​

Отладка в IDE​

  • IntelliJ IDEA и Eclipse имеют отличную поддержку Groovy.
  • Точки останова работают в динамическом и статическом режимах.

Логирование состояния​

  • Используйте dump() для быстрого инспектирования объекта:
println person.dump()

Мониторинг производительности​

  • VisualVM показывает вызовы Groovy-методов как обычные JVM-методы.
  • При использовании indy — убедитесь, что JIT работает эффективно.

41. Обновление и миграция​

Groovy 2 → 3 → 4​

Основные изменения:

  • Groovy 3 — новые операторы (!in, !instanceof), поддержка Java 13+ синтаксиса.
  • Groovy 4 — Jakarta EE вместо javax, улучшенная поддержка модулей, JDK 17+.

Проверка совместимости​

  • Запустите тесты с новой версией.
  • Используйте @CompileStatic для выявления скрытых ошибок.

42. Когда использовать Groovy — и когда нет​

Использовать Groovy, если​

  • Нужен выразительный DSL.
  • Требуется быстрая автоматизация.
  • Интеграция с существующим Java-кодом.
  • Пишутся тесты (Spock).
  • Создаётся конфигурационная система.

Рассмотреть альтернативы (Kotlin, Java), если​

  • Производительность критична на каждом этапе.
  • Команда не знакома с динамическими языками.
  • Требуется строгая типизация на этапе компиляции.
  • Проект масштабируется до сотен тысяч строк.

Основа по протоколу

Базовый разбор HTTP и HTTPS находится в отдельной статье — HTTP как основа веб-интеграций.


В подборках​

Статья входит в тематические подборки и блок "С чего начать?" на главной. Соседние шаги того же маршрута:

Справочники — Справочник по языку Ruby, Справочник по языку Rust, Справочник по языку Go, Справочник по языку Swift, Справочник по Kotlin, Справочник по Lua.


Содержание