Профили Maven: объявление, активация, -P и activeByDefault - Вопросы
Всего: 5 вопросов
1. Что такое профиль Maven, как его объявить и что можно переопределить в профиле?
Что такое профиль 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?
Какими способами активируется профиль 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- не задано; nameenvи valueci--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?
Как с помощью профилей 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 активны, и как действуют профили родительского 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 и 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.