Введение: Что такое Maven и Gradle и зачем они нужны?
В мире Java-разработки существует фундаментальная проблема: как управлять зависимостями (внешними библиотеками), автоматизировать сборку проекта, запускать тесты и создавать финальные артефакты (JAR, WAR)? Ручное скачивание JAR-файлов и настройка classpath — это путь в никуда, особенно для проектов с десятками зависимостей.
Maven и Gradle — это две самые популярные системы автоматической сборки (build automation tools) для Java. Они решают следующие задачи:
- Управление зависимостями: автоматическое скачивание библиотек из центральных репозиториев (Maven Central, Google Maven) и их транзитивных зависимостей.
- Стандартизация жизненного цикла: компиляция, тестирование, упаковка, развертывание — все это выполняется стандартными командами.
- Воспроизводимость сборок: любой разработчик может собрать проект одной командой, имея только исходный код и файл конфигурации.
- Интеграция с CI/CD: Jenkins, GitLab CI, GitHub Actions легко запускают Maven/Gradle сборки.
Maven использует XML (файл pom.xml) и строгий жизненный цикл. Gradle использует Groovy или Kotlin DSL (файл build.gradle или build.gradle.kts), он более гибкий и быстрый за счет инкрементальной сборки. В этой статье мы рассмотрим оба инструмента, но сфокусируемся на Gradle как на более современном решении.
Установка Maven и Gradle
Установка Maven
Maven не устанавливается через pip или npm. Его нужно скачать с официального сайта или установить через пакетный менеджер ОС.
# macOS (Homebrew)
brew install maven
# Ubuntu/Debian
sudo apt-get update
sudo apt-get install maven
# Windows (Chocolatey)
choco install maven
# Проверка установки
mvn --version
Установка Gradle
Gradle также устанавливается отдельно. Рекомендуется использовать SDKMAN! для управления версиями.
# Установка SDKMAN (если еще не установлен)
curl -s "https://get.sdkman.io" | bash
source "$HOME/.sdkman/bin/sdkman-init.sh"
# Установка последней версии Gradle
sdk install gradle
# Проверка
gradle --version
# Альтернативно: скачать с https://gradle.org/releases/ и распаковать
Быстрый старт: Создание проекта
Создание проекта с Maven
Maven может генерировать скелет проекта через архетипы (archetypes).
# Создаем простой Java-проект
mvn archetype:generate -DgroupId=com.example -DartifactId=my-app -DarchetypeArtifactId=maven-archetype-quickstart -DinteractiveMode=false
# Переходим в папку проекта
cd my-app
# Сборка проекта
mvn clean package
# Запуск (если main class настроен)
java -cp target/my-app-1.0-SNAPSHOT.jar com.example.App
Создание проекта с Gradle
Gradle использует команду init для создания скелета.
# Создаем папку и инициализируем проект
mkdir my-gradle-app
cd my-gradle-app
gradle init
# Выбираем: 2: application -> 3: Java -> 1: Groovy DSL -> 2: JUnit Jupiter -> Enter
# Сборка и запуск
./gradlew build
./gradlew run
После этого у вас появится структура проекта с файлами build.gradle (или pom.xml для Maven) и папками src/main/java и src/test/java.
Основные методы/функции (Gradle DSL)
Рассмотрим ключевые конструкции Gradle (Groovy DSL). Для Maven они аналогичны, но синтаксис XML.
1. dependencies { ... }
Что делает: Определяет зависимости проекта — внешние библиотеки, которые будут скачаны из репозиториев.
Параметры: Внутри блока указываются конфигурации (implementation, testImplementation, compileOnly и др.) и координаты библиотеки (group:name:version).
dependencies {
// Основная зависимость (будет включена в финальный JAR)
implementation 'com.google.guava:guava:31.1-jre'
// Зависимость только для тестов
testImplementation 'org.junit.jupiter:junit-jupiter:5.9.2'
// Зависимость, доступная только во время компиляции (не попадает в JAR)
compileOnly 'org.projectlombok:lombok:1.18.26'
annotationProcessor 'org.projectlombok:lombok:1.18.26'
}
2. repositories { ... }
Что делает: Указывает, откуда скачивать зависимости. По умолчанию — Maven Central.
Параметры: Имена репозиториев (mavenCentral(), google(), mavenLocal(), jcenter() — устарел).
repositories {
// Центральный репозиторий Maven
mavenCentral()
// Локальный репозиторий (~/.m2/repository)
mavenLocal()
// Репозиторий Google (для Android)
google()
// Собственный репозиторий по URL
maven { url 'https://jitpack.io' }
}
3. plugins { ... }
Что делает: Подключает плагины, которые расширяют возможности Gradle (например, для сборки Spring Boot, создания fat JAR).
Параметры: id плагина и версия (опционально).
plugins {
// Плагин для Java-проекта
id 'java'
// Плагин для Spring Boot
id 'org.springframework.boot' version '3.1.0'
// Плагин для управления версиями зависимостей
id 'io.spring.dependency-management' version '1.1.0'
}
4. java { ... }
Что делает: Настраивает версию Java, совместимость исходников и байт-кода.
Параметры: sourceCompatibility, targetCompatibility, toolchain.
java {
// Версия исходного кода
sourceCompatibility = JavaVersion.VERSION_17
// Версия байт-кода
targetCompatibility = JavaVersion.VERSION_17
// Использование toolchain (скачивание JDK, если нет)
toolchain {
languageVersion = JavaLanguageVersion.of(17)
}
}
5. application { ... }
Что делает: Настраивает запуск приложения (главный класс). Используется с плагином 'application'.
Параметры: mainClass, applicationName.
application {
// Главный класс для запуска
mainClass = 'com.example.Main'
// Имя исполняемого файла (опционально)
applicationName = 'my-app'
}
6. test { ... }
Что делает: Настраивает выполнение тестов (JUnit, TestNG).
Параметры: useJUnitPlatform(), useTestNG(), systemProperties, testLogging.
test {
// Использовать JUnit Platform (для JUnit 5)
useJUnitPlatform()
// Логирование тестов
testLogging {
events "passed", "skipped", "failed"
showStandardStreams = true
}
// Системные свойства для тестов
systemProperty "env", "test"
}
7. jar { ... }
Что делает: Настраивает создание JAR-файла (манифест, включение зависимостей).
Параметры: manifest, archiveFileName, from.
jar {
// Настройка манифеста
manifest {
attributes(
'Main-Class': 'com.example.Main',
'Implementation-Version': '1.0.0'
)
}
// Имя выходного файла
archiveFileName = 'my-app.jar'
// Включить все зависимости (fat JAR) — лучше использовать Shadow plugin
from {
configurations.runtimeClasspath.collect { it.isDirectory() ? it : zipTree(it) }
}
duplicatesStrategy = DuplicatesStrategy.EXCLUDE
}
8. tasks.register('taskName') { ... }
Что делает: Создает пользовательскую задачу Gradle. Можно выполнить через gradle taskName.
Параметры: Имя задачи, тип (Copy, Delete, Exec), действия (doFirst, doLast).
tasks.register('printVersion') {
doLast {
println "Версия проекта: ${version}"
}
}
tasks.register('copyResources', Copy) {
from 'src/main/resources'
into 'build/resources'
}
// Выполнение: gradle printVersion
9. configurations { ... }
Что делает: Позволяет создавать собственные конфигурации зависимостей (например, для отдельного набора библиотек).
Параметры: Имя конфигурации, extendsFrom, resolutionStrategy.
configurations {
// Создаем конфигурацию для инструментов разработки
devTools
// Наследуем от implementation
implementation.extendsFrom devTools
}
dependencies {
devTools 'org.projectlombok:lombok:1.18.26'
annotationProcessor 'org.projectlombok:lombok:1.18.26'
}
// Использование: gradle dependencies --configuration devTools
10. allprojects / subprojects { ... }
Что делает: Применяет конфигурацию ко всем проектам (в мультимодульном проекте) или только к подпроектам.
Параметры: Блоки с настройками (repositories, dependencies, plugins).
// В корневом build.gradle
allprojects {
repositories {
mavenCentral()
}
}
subprojects {
apply plugin: 'java'
dependencies {
testImplementation 'org.junit.jupiter:junit-jupiter:5.9.2'
}
}
Реальный практический пример: Веб-сервис на Spring Boot
Создадим полноценный микросервис с использованием Gradle и Spring Boot.
Структура проекта
demo-service/
├── build.gradle
├── settings.gradle
└── src/
└── main/
├── java/
│ └── com/example/demo/
│ ├── DemoApplication.java
│ ├── controller/
│ │ └── HelloController.java
│ └── service/
│ └── GreetingService.java
└── resources/
└── application.properties
Файл build.gradle
plugins {
id 'java'
id 'org.springframework.boot' version '3.1.0'
id 'io.spring.dependency-management' version '1.1.0'
}
group = 'com.example'
version = '0.0.1-SNAPSHOT'
java {
sourceCompatibility = '17'
}
repositories {
mavenCentral()
}
dependencies {
implementation 'org.springframework.boot:spring-boot-starter-web'
implementation 'org.springframework.boot:spring-boot-starter-actuator'
testImplementation 'org.springframework.boot:spring-boot-starter-test'
}
tasks.named('test') {
useJUnitPlatform()
}
Код приложения
// DemoApplication.java
package com.example.demo;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class DemoApplication {
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
}
// HelloController.java
package com.example.demo.controller;
import com.example.demo.service.GreetingService;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org