Файл pom.xml в Maven: структура, GAV, properties, packaging, build - Вопросы

Всего: 5 вопросов

1. 

Из каких элементов состоит 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 — тройка 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> задаёт, какой артефакт получится в результате сборки, и тем самым определяет стандартные привязки целей плагинов к фазам жизненного цикла (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, например в версии зависимостей и настройки плагинов. Для отдельных полей есть ограничения: координаты <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 и как посмотреть итоговую конфигурацию проекта?

Каждый 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. Это главный инструмент, когда непонятно, откуда взялась настройка или почему не применилось свойство.

Страница 1 из 1