Введение в Java Maven
Что такое Maven, как он собирает проекты Java и как установить и запускать команды mvn.
Введение в Java Maven
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, на который нацелен компилятор.
Зависимости и транзитивный 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 означает, что её предоставляет среда выполнения.
| Scope | В compile-classpath | В test-classpath | Упакована | Типичное применение |
|---|---|---|---|---|
compile (по умолчанию) | Да | Да | Да | Обычные библиотеки |
provided | Да | Да | Нет | Servlet API, предоставляется в среде выполнения |
runtime | Нет | Да | Да | Драйверы JDBC |
test | Нет | Да | Нет | JUnit, Mockito |
Жизненный цикл сборки
Сборки Maven проходят через фиксированную последовательность фаз. Ключевые фазы стандартного жизненного цикла — это validate, compile, test, package, verify, install и deploy. Запуск фазы выполняет каждую фазу перед ней — mvn package сначала валидирует, компилирует и тестирует, затем упаковывает. Вы никогда не вызываете фазы вне порядка.
mvn compile # скомпилировать основные исходники
mvn test # компиляция + запуск юнит-тестов
mvn package # компиляция + тесты + сборка JAR/WAR
mvn install # упаковка + копирование артефакта в ваш локальный репозиторий
mvn clean package # сначала удалить target/, затем собрать с нуляКаждая фаза привязана к одной или нескольким целям (goals), предоставляемым плагинами (например, compiler:compile привязана к фазе compile). В плагинах живёт фактическая работа; жизненный цикл лишь упорядочивает её.
Репозитории
Maven получает артефакты из репозиториев. При сборке он сначала смотрит в ваш локальный репозиторий (~/.m2/repository), кэш на вашей машине. При промахе он загружает из удалённого репозитория — по умолчанию Maven Central — и сохраняет копию локально, чтобы следующая сборка была быстрой и офлайн. Команды часто добавляют приватный репозиторий для внутренних библиотек.
pom.xml проекта → локальный репо (~/.m2) → удалённый репо (Maven Central)
(попадание в кэш?) (загрузка + кэширование)Запускаемый пример
В исполнителе кода нет Maven в classpath, поэтому программа ниже моделирует основную механику Maven обычным кодом JDK: она хранит крошечный POM как map, разрешает транзитивное замыкание зависимостей (устраняя дубликаты общих артефактов) и проходит по жизненному циклу сборки, останавливаясь на запрошенной фазе. Формы здесь — координаты 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, когда вы запускаете 'mvn package'?