Файл pom.xml в Maven: структура, GAV, properties, packaging, build - Вопросы
Всего: 5 вопросов
1. Из каких элементов состоит pom.xml, какие из них обязательны и что означает modelVersion?
Из каких элементов состоит pom.xml, какие из них обязательны и что означает modelVersion?
pom.xml — XML-файл в корне Maven-проекта с POM (Project Object Model). Обязательны только корневой <project>, <modelVersion> и координаты groupId, artifactId, version (groupId и version можно унаследовать от parent). Без них Maven не прочитает POM или выдаст ошибку вида 'groupId' is missing.
Необязательны packaging, name/description/url, properties, dependencies, build и parent. Неуказанные настройки могут наследоваться от родителя и Super POM (стандартные каталоги, ресурсы, finalName, Maven Central) либо браться из модели POM (packaging = jar) или самих плагинов, а необязательный элемент может просто отсутствовать. Стандартные привязки целей плагинов к фазам задаёт lifecycle mapping для выбранного packaging. Порядок элементов на результат не влияет, но принято писать координаты, описание, свойства, зависимости, сборку.
modelVersion = 4.0.0 сообщает, по какой версии модели POM написан файл; для Maven 3 это единственное допустимое значение. В Maven 4 появилась модель 4.1.0, но файлы с 4.0.0 он читает, поэтому для большинства проектов пишут 4.0.0. Атрибуты xmlns и xsi:schemaLocation необязательны, но позволяют IDE проверять и подсказывать теги; xmlns — идентификатор пространства имён, а не адрес, поэтому http в нём менять на https не нужно.
2. Что такое координаты GAV в pom.xml и чем версия SNAPSHOT отличается от релиза?
Что такое координаты GAV в pom.xml и чем версия SNAPSHOT отличается от релиза?
GAV — тройка groupId (организация в формате перевёрнутого домена), artifactId (имя проекта) и version, которая однозначно определяет проект или библиотеку в мире Maven. Пара groupId + artifactId без версии обозначает проект в целом, но не конкретную сборку, а конкретный файл дополнительно различается расширением (типом) и при необходимости classifier (например, jar с исходниками -sources). Из координат складываются путь и имя файла: com.examclouds:shop:1.0-SNAPSHOT после mvn install окажется в ~/.m2/repository/com/examclouds/shop/1.0-SNAPSHOT/shop-1.0-SNAPSHOT.jar.
SNAPSHOT (суффикс -SNAPSHOT, например 1.0-SNAPSHOT) — версия в разработке: её содержимое может меняться. Новую сборку SNAPSHOT-зависимости Maven ищет в удалённом репозитории при сборке, если подошёл срок по updatePolicy этого репозитория (по умолчанию daily — не чаще раза в сутки); принудительно обновить SNAPSHOT-зависимости можно флагом mvn -U. Maven Central в Super POM подключён с запретом snapshots, поэтому SNAPSHOT-версии берут из отдельного (обычно корпоративного) репозитория.
Релиз — версия без суффикса (1.0.0). Опубликованный релиз считается неизменным, а в Maven Central его нельзя ни перезаписать, ни удалить, поэтому исправление выпускают новой версией (1.0.1).
3. Что задаёт элемент packaging в pom.xml и чем отличаются jar, war и pom?
Что задаёт элемент packaging в pom.xml и чем отличаются jar, war и pom?
<packaging> задаёт, какой артефакт получится в результате сборки, и тем самым определяет стандартные привязки целей плагинов к фазам жизненного цикла (lifecycle mapping). Элемент необязателен: если его нет, используется jar — значение по умолчанию самой модели POM.
- jar —
target/artifactId-version.jar, на фазе package работает maven-jar-plugin; консольные приложения, библиотеки, Spring Boot-приложения. - war — веб-архив с содержимым
src/main/webapp(maven-war-plugin) для развёртывания на Tomcat или другом сервлет-контейнере. - pom — только сам pom.xml, без кода и jar: компиляция и упаковка не выполняются. Используется для родительских POM, агрегаторов многомодульного проекта (список
<modules>), BOM и других проектов, публикующих только POM. - maven-plugin, ear, ejb — плагин Maven, корпоративный архив Jakarta EE, EJB-модуль; специальные случаи со своими плагинами.
Из-за этой привязки смена packaging меняет поведение сборки целиком: если поставить pom в проекте с кодом, mvn package завершится BUILD SUCCESS, но не скомпилирует ни одного класса.
4. Как работают свойства properties и выражения ${...} в pom.xml?
Как работают свойства properties и выражения ${...} в pom.xml?
<properties> хранит пары «имя — значение», которые через выражение ${...} с именем свойства подставляются во многие элементы POM, например в версии зависимостей и настройки плагинов. Для отдельных полей есть ограничения: координаты <parent> в Maven 3 должны быть литералами. Свойства убирают повторы (одна версия для нескольких библиотек, например ${junit.version}) и передают параметры плагинам: maven.compiler.release — версия Java, project.build.sourceEncoding — кодировка. В Maven 3.9.x без заданной или унаследованной кодировки плагины могут взять платформенную и выдать предупреждение; с Maven 3.10.0 UTF-8 задан в Super POM. Свои свойства называют любым допустимым именем XML-элемента; точки в имени — просто часть имени.
Встроенные значения: ${project.version}, ${project.groupId}, ${project.artifactId}, ${project.basedir}, ${project.build.directory}, ${project.build.finalName}; переменные окружения с префиксом env. (${env.JAVA_HOME}); системные свойства JVM (${java.version}, ${user.home}).
Переопределение: mvn package -Djunit.version=5.12.0 — значение из -D важнее properties, файл не меняется. Короткие формы ${pom.version} и ${version} устарели (предупреждение is deprecated) — пишите ${project.version}.
Опечатка в ${...} не всегда вызывает немедленную ошибку: в версии зависимости это ошибка проверки модели (недопустимая версия), в фильтруемом ресурсе выражение может остаться без замены, в настройке плагина результат зависит от параметра и плагина. Проверить подстановку в модели помогает effective POM.
5. Что такое parent, Super POM и effective POM в Maven и как посмотреть итоговую конфигурацию проекта?
Что такое parent, Super POM и effective POM в Maven и как посмотреть итоговую конфигурацию проекта?
Каждый pom.xml наследует настройки от родителя — явного или неявного.
- parent — явный родительский POM с
packaging= pom. Дочерний проект ссылается на него по GAV в<parent>(по умолчанию родитель ищется в../pom.xml) и получает groupId, version, свойства, зависимости и pluginManagement.artifactIdне наследуется: каждый модуль указывает свой, иначе у модулей совпали бы координаты. Так устроены многомодульные проекты и Spring Boot (spring-boot-starter-parent). - Super POM — встроенный в Maven неявный родитель всех проектов: стандартные каталоги
src/main/javaиtarget, ресурсы, finalName, репозиторий Maven Central. Поэтому минимальный pom.xml из нескольких строк уже собирает проект. Но не всё «по умолчанию» оттуда: packaging = jar — значение модели POM, привязки плагинов к фазам задаёт lifecycle mapping для packaging. - Effective POM — итоговая модель, которую Maven получает после наследования, активации профилей и подстановки свойств: пути абсолютные, свойства подставлены, видны версии плагинов по умолчанию и унаследованные зависимости. Это не все фактические параметры исполнения плагинов (значения по умолчанию внутри плагина в нём не видны) и не содержимое отфильтрованных файлов.
Посмотреть его: mvn help:effective-pom, сохранить в файл: mvn help:effective-pom -Doutput=effective-pom.xml. Это главный инструмент, когда непонятно, откуда взялась настройка или почему не применилось свойство.