Введение в Java Maven
Что такое Maven, как он собирает Java-проекты, как установить и запускать команды mvn.
Maven — стандартный инструмент автоматизации сборки и управления зависимостями для Java. Он превращает проект в декларативное описание — что это такое, от чего зависит, как собирается — и затем выполняет сборку за вас. Вместо того чтобы вручную управлять JAR-файлами и флагами javac, вы декларируете свои потребности в одном файле, а Maven загружает зависимости, компилирует, тестирует и упаковывает ваш код через предсказуемый, воспроизводимый жизненный цикл.
POM: проект как данные
Каждый проект Maven описывается файлом pom.xml (Project Object Model). Он идентифицирует проект тремя координатами — groupId, artifactId и version (вместе «GAV») — и перечисляет нужные библиотеки. Та же схема координат именует ваш проект и каждую зависимость, что позволяет Maven находить артефакты в репозитории.
<project xmlns="http://maven.apache.org/POM/4.0.0">
<modelVersion>4.0.0</modelVersion>
<groupId>com.example</groupId>
<artifactId>shop-app</artifactId>
<version>1.0.0</version>
<packaging>jar</packaging>
<properties>
<maven.compiler.release>21</maven.compiler.release>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<version>6.1.0</version>
</dependency>
</dependencies>
</project>Элемент <packaging> указывает Maven, что создавать (jar, war, pom). Блок <properties> содержит переиспользуемые значения — здесь это целевая версия Java для компилятора. POM расширяется, охватывая плагины, профили и наследование; в главе Maven POM эти части разобраны подробно.
Зависимости и транзитивный classpath
Вы перечисляете только свои прямые зависимости. Maven читает POM каждой из них и подтягивает всё, что нужно им — транзитивные зависимости, — автоматически формируя полный classpath. Объявление spring-web также принесёт spring-core, без явного указания.
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.17.0</version>
</dependency>Каждая зависимость имеет scope, определяющий, когда она присутствует в classpath. Значение по умолчанию — compile — делает её доступной везде; test ограничивает только тестовым кодом; provided означает, что среда выполнения предоставит её сама. Подробнее об исключениях конфликтов версий и dependencyManagement — в разделе Maven dependencies.
| Scope | В compile classpath | В test classpath | Упакована | Типичное применение |
|---|---|---|---|---|
compile (по умолчанию) | Да | Да | Да | Обычные библиотеки |
provided | Да | Да | Нет | Servlet API, предоставляется в runtime |
runtime | Нет | Да | Да | JDBC-драйверы |
test | Нет | Да | Нет | JUnit, Mockito |
Жизненный цикл сборки
Сборки Maven проходят через фиксированную последовательность фаз. Ключевые фазы стандартного жизненного цикла: validate, compile, test, package, verify, install и deploy. Запуск фазы запускает все предшествующие — mvn package сначала валидирует, компилирует и тестирует, а затем упаковывает. Фазы никогда не вызываются не по порядку.
mvn compile # compile main sources
mvn test # compile + run unit tests
mvn package # compile + test + build the JAR/WAR
mvn install # package + copy artifact into your local repository
mvn clean package # delete target/ first, then build freshКаждая фаза привязана к одной или нескольким целям (goals), предоставляемым плагинами (например, compiler:compile привязана к фазе compile). Именно в плагинах выполняется реальная работа; жизненный цикл лишь упорядочивает её. В главе Maven build lifecycle рассматриваются все три встроенных жизненных цикла и привязка целей к фазам.
Репозитории
Maven получает артефакты из репозиториев. При сборке он сначала ищет в вашем локальном репозитории (~/.m2/repository) — кэше на вашем компьютере. При промахе загружает из удалённого репозитория — по умолчанию Maven Central — и сохраняет копию локально, чтобы следующая сборка была быстрой без сети. Команды часто добавляют приватный репозиторий для внутренних библиотек.
project pom.xml → local repo (~/.m2) → remote repo (Maven Central)
(cache hit?) (download + cache)Рабочий пример
Среда выполнения не имеет Maven в своём classpath, поэтому программа ниже моделирует ключевую механику Maven с помощью обычного JDK-кода: хранит небольшой POM в виде карты, разрешает транзитивное замыкание зависимостей (удаляя дублирующиеся артефакты) и проходит по жизненному циклу сборки, останавливаясь на запрошенной фазе. Конструкции здесь — GAV-координаты, транзитивное разрешение, упорядоченные фазы — точно соответствуют тому, что делает настоящий Maven.
Что следует усвоить из запуска:
- Проект и каждая зависимость именуются одним и тем же GAV-тройником, вот почему
Project coordinates: com.example:shop-app:1.0.0читается так же, как строка зависимости. - Объявлены только две зависимости, но разрешённый classpath содержит четыре JAR —
spring-coreиjackson-annotationsбыли подтянуты транзитивно, точно как это делает Maven. - Множество
seenгарантирует, что каждый артефакт появится один раз; это дедупликация Maven, предотвращающая попадание общей библиотеки в classpath дважды. Executing: mvn packageвыполняетvalidate,compileиtestпередpackage, а затем останавливается — запуск фазы всегда запускает все предшествующие фазы по порядку.- Сборка останавливается на
packageи никогда не достигаетinstall, отражая то, как запрошенная цель ограничивает продвижение жизненного цикла.
Когда стоит использовать Maven
Maven отлично подходит для стандартных Java и JVM-проектов: его соглашения «convention over configuration» (исходники в src/main/java, тесты в src/test/java, результаты в target/) означают, что новый участник может собрать любой Maven-проект одинаковым способом. Его декларативный XML легко читается и сравнивается, а поддержка в IDE зрелая. Компромисс — многословность и ограниченная гибкость для нестандартных сборок. Там, где нужны скриптовые, сильно кастомизированные сборки, распространённой альтернативой является Gradle — он использует программируемый скрипт сборки вместо декларативного XML, но охватывает ту же область: GAV-координаты, транзитивные зависимости и граф задач (вместо фаз).
Следующие шаги
- Maven POM — полная структура
pom.xml, включая плагины и наследование. - Maven dependencies — области видимости, исключения и разрешение конфликтов версий в деталях.
- Maven build lifecycle — все фазы, три жизненных цикла и привязка целей.
- Gradle introduction — скриптовая альтернатива Maven.