Профили Maven: объявление, активация, -P и activeByDefault - Вопросы

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

1. 

Что такое профиль Maven, как его объявить и что можно переопределить в профиле?

Профиль Maven - именованный набор настроек POM внутри <profiles>, который применяется поверх основной модели только при активации: вручную ключом -P или по условию из <activation>. Профили позволяют одной сборке вести себя по-разному без копий pom.xml: свойства для окружений dev/test/prod, проверки на CI, интеграционные тесты, опциональный модуль, настройки под JDK или ОС.

Объявление: каждый <profile> обязан иметь уникальный <id>, может содержать <activation> и разрешённые профилю разделы. Свойства профиля подставляются туда же, куда обычные <properties>. В многомодульном проекте профиль из -P включается во всех модулях reactor, где профиль с таким id объявлен (в том числе через родителя). Внешний profiles.xml был в Maven 2, Maven 3 его не поддерживает.

Можно: properties; dependencies и dependencyManagement; modules (например, shop-e2e-tests собирается только по mvn verify -P e2e); в build - plugins, pluginManagement, resources, testResources, filters, finalName, defaultGoal (плагин профиля добавляется к основным, execution с тем же id объединяется); repositories, pluginRepositories, distributionManagement, reporting.

Нельзя: groupId, artifactId, version, packaging, parent, а также sourceDirectory, testSourceDirectory, outputDirectory, testOutputDirectory и extensions.

Профиль меняет сам артефакт: jar, собранный с -P prod, отличается от собранного без него.

2. 

Какими способами активируется профиль Maven?

Вручную: -P prod, -P prod,it или <activeProfiles> в settings.xml. -P '!dev' или -P -dev выключает профиль в этом запуске, даже если его условие выполнено.

По умолчанию: activeByDefault действует, только пока в том же POM не активирован другой профиль (ключом -P или по условию), и выключается молча. Надёжнее отсутствие свойства (!prod) или явный -P dev,it.

По условию <activation>:

  • свойство: name ci - задано с любым значением (-Dci); !ci - не задано; name env и value ci - -Denv=ci; value !ci по документации Maven - свойство не задано или не равно ci; переменные окружения в Maven 3 - как env.CI;
  • JDK: 25 - версия начинается с префикса, [17,21) - от 17 включительно до 21 не включая, !1.8 - не начинается с префикса;
  • ОС: family (windows, unix, mac), а также name, arch, version;
  • файл: exists или missing; в пути допустимы ${basedir}, системные свойства и переменные окружения, но не <properties>.

Несколько условий в одном activation с Maven 3.2.2 должны выполняться все (раньше хватало одного). В Maven 3 условие property видит системные свойства и -D, но не <properties> POM, поэтому один профиль не включит другой своим свойством: дайте им общее условие или перечислите оба (-P ci,it).

3. 

Как с помощью профилей Maven подставлять настройки окружения в ресурсы и чем профили Maven отличаются от профилей Spring?

Профиль и фильтрация: профиль задаёт свойство (например, db.url), и при копировании src/main/resources с включённой фильтрацией (<filtering>true</filtering>) Maven заменяет ${db.url} значением из активного профиля. С dev (activeByDefault) и prod строка db.url=${db.url} после mvn package станет db.url=jdbc:h2:mem:shop, после mvn package -P prod - db.url=jdbc:postgresql://db.example.com/shop. Если свойств много, профиль подключает файл фильтров: <filters><filter>src/main/filters/prod.properties</filter></filters> в build.

Осталась строка ${db.url} - профиль не активен или для каталога не включена фильтрация. Профиль активен, а значение не то - то же свойство передано через -D, оно приоритетнее.

Профиль Maven и профиль Spring - разные механизмы с одинаковым названием. Профиль Maven действует при сборке (включается -P или <activation>) и меняет сам артефакт: для каждого окружения свой jar. Профиль Spring действует при запуске (application-{profile}.properties, @Profile; включается spring.profiles.active или SPRING_PROFILES_ACTIVE) и выбирает конфигурацию внутри одного артефакта. Для адресов, логинов, уровней логирования обычно удобнее профили Spring или переменные окружения; профили Maven оставляют для того, что меняет сборку: состав модулей, плагины проверок, зависимости под конкретную JDK.

4. 

Как проверить, какие профили Maven активны, и как действуют профили родительского POM в модулях?

Проблемы с профилями обычно молчаливые: сборка проходит, но не с теми настройками. Поэтому проверяют командами maven-help-plugin с теми же ключами, что и сборку:

  • mvn help:active-profiles - для каждого модуля активные профили и источник каждого (POM или settings.xml), примерный вид строки: - dev (source: com.examclouds:shop-parent:1.0-SNAPSHOT);
  • mvn help:all-profiles - все объявленные профили с признаком активности (формат зависит от версии плагина), по нему сверяют id;
  • mvn help:effective-pom и mvn help:effective-pom -P prod - итоговые модели; их сравнение (например, с -Doutput=base.xml и -Doutput=prod.xml) показывает, что добавляет профиль, без запуска сборки.

Профиль из -P, которого нет ни в одном POM, Maven 3.9.x отмечает лишь предупреждением вида The requested profile "prd" could not be activated because it does not exist. - опечатка в скрипте CI сборку не роняет.

Профили родителя действуют в модулях тоньше, чем обычное наследование: если условие профиля, объявленного в родителе, выполнено при сборке модуля, профиль применяется к модели родителя, и модуль получает результат - свойства, зависимости, плагины. Сам профиль модулю не принадлежит; откуда он пришёл, видно по source в help:active-profiles, итоговую модель показывает help:effective-pom в каталоге модуля.

5. 

Как работают профили в settings.xml и activeProfiles и почему не стоит хранить пароли в профилях pom.xml?

Профили в settings.xml: в ~/.m2/settings.xml профиль может содержать только <activation>, <properties>, <repositories> и <pluginRepositories>. Там хранят настройки конкретной машины - адрес корпоративного репозитория или локальные пути.

activeProfiles: id в <activeProfiles><activeProfile>company</activeProfile></activeProfiles> активирует профиль с таким именем при каждом запуске Maven на этой машине, как если бы его передали в -P. Всё, что влияет на результат сборки, держат в pom.xml, иначе у коллег и на CI проект соберётся по-другому.

Почему не пароли в профилях pom.xml: pom.xml хранится в Git, а mvn deploy публикует его в репозиторий артефактов вместе со всеми профилями. Строка <db.password>secret</db.password> в профиле prod видна всем, у кого есть доступ к Git, и всем, кто скачивает POM из Nexus или Maven Central; если секрет подставляется фильтрацией в ресурсы, он оказывается и внутри jar. Удалить его из истории Git и опубликованных версий гораздо сложнее, чем не добавлять.

Где хранить секреты: пароль базы приложение получает при запуске (переменная окружения, хранилище секретов), а учётные данные для репозиториев Maven берутся из <servers> в settings.xml или из секретов CI.

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