Maven ·
‹ Предыдущий Следующий ›
⏱ 5 минут чтения Обновлено: 2026-11-07

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

В pom.xml два профиля: dev с <activeByDefault>true</activeByDefault>, задающий адрес базы db.url, и it для интеграционных тестов. Разработчик запускает mvn verify -P it, сборка проходит, но в target/classes/app.properties вместо адреса базы лежит строка db.url=${db.url}. Профиль dev молча выключился: activeByDefault действует, только пока в этом POM не активирован никакой другой профиль.

Профиль Maven (Maven profile) — это именованный набор настроек POM внутри элемента <profiles>, который применяется поверх основной модели только при активации: вручную ключом -P или автоматически по условию из <activation> (свойство, версия JDK, операционная система, наличие файла). Профили позволяют одной сборке вести себя по-разному в разных окружениях без копий pom.xml. Примеры рассчитаны на Maven 3.9.x.

Зачем нужны профили Maven

Профили нужны, когда один и тот же проект надо собирать немного по-разному: с другими свойствами для окружения, с дополнительными проверками на CI, с медленными тестами или модулем только по запросу, с настройками под конкретную версию JDK или ОС. Вместо нескольких копий pom.xml различия описываются профилями, а нужный набор включается при запуске.

Сценарий Что меняет профиль Как обычно включают
Окружения dev / test / prod Свойства (адрес сервиса, уровень логирования), подставляемые в ресурсы -P prod; dev — по умолчанию
Проверки на CI Плагины статического анализа, покрытия, подписи артефактов По свойству (-Dci) или -P ci в скрипте CI
Интеграционные тесты Плагин failsafe, тестовая база, дополнительные зависимости -P it
Опциональный модуль <modules>: модуль входит в сборку только при активации -P e2e
Разные JDK и ОС Параметры компилятора, нативные библиотеки, пути Автоматически: <jdk>, <os>

Профиль меняет то, что получается на выходе сборки: jar, собранный с -P prod, отличается от собранного без него. Поэтому настройки, которые можно задать при запуске приложения (переменные окружения, внешний конфиг), лучше не зашивать в сборку — подробнее в разделах Профили Maven и Spring profiles и Почему не хранить пароли.

Как объявить профиль: profiles, profile, id

Профили объявляют в элементе <profiles> файла pom.xml: каждый <profile> обязан иметь уникальный <id>, по которому его включают ключом -P, может содержать условие <activation> и любые разделы, которые профилю разрешено переопределять (<properties>, <dependencies>, <build> и др.).

<profiles>
    <profile>
        <id>dev</id>
        <activation>
            <activeByDefault>true</activeByDefault>
        </activation>
        <properties>
            <app.env>dev</app.env>
            <db.url>jdbc:h2:mem:shop</db.url>
        </properties>
    </profile>
    <profile>
        <id>prod</id>
        <properties>
            <app.env>prod</app.env>
            <db.url>jdbc:postgresql://db.example.com/shop</db.url>
        </properties>
    </profile>
</profiles>

Свойства профиля подставляются туда же, куда и обычные свойства из <properties>: в зависимости, настройки плагинов, фильтруемые ресурсы. Включение вручную:

mvn package -P prod          # activate prod
mvn package -P prod,it       # several profiles
mvn package -P '!dev'        # deactivate dev (quote the ! in bash)

В многомодульном проекте профиль из -P включается во всех модулях reactor, где профиль с таким id объявлен (в том числе через родительский POM). Внешний файл profiles.xml рядом с pom.xml, который встречается в старых статьях, был в Maven 2; Maven 3 его не поддерживает.

Что можно переопределить в профиле

Профиль в pom.xml может содержать почти те же разделы, что и сам POM: свойства, зависимости, модули, плагины, ресурсы, репозитории. Недоступны профилю координаты проекта, <parent> и часть настроек <build> — каталоги исходников и вывода, а также расширения сборки.

Раздел Можно в профиле POM? Типичное применение
properties Да Адрес БД, имя окружения, флаги плагинов
dependencies, dependencyManagement Да Драйвер БД или тестовая библиотека только для одного окружения
modules Да Дополнительный модуль, который собирается только по запросу
build: plugins, pluginManagement, resources, testResources, filters, finalName, defaultGoal Да Включить проверки кода на CI, другой каталог ресурсов или файл фильтров
repositories, pluginRepositories, distributionManagement, reporting Да Другой репозиторий для публикации
build: sourceDirectory, testSourceDirectory, outputDirectory, testOutputDirectory, extensions Нет —
groupId, artifactId, version, packaging, parent Нет —

Сценарий «дополнительный модуль». Медленные сквозные тесты выносят в модуль shop-e2e-tests и подключают его к reactor только в профиле:

<!-- shop-parent/pom.xml -->
<profiles>
    <profile>
        <id>e2e</id>
        <modules>
            <module>shop-e2e-tests</module>
        </modules>
    </profile>
</profiles>

Обычная mvn verify собирает три модуля магазина, а mvn verify -P e2e — четыре. Как устроены агрегация и reactor, разобрано в уроке Многомодульный проект Maven.

Сценарий «плагин только в профиле». Плагин, объявленный в <build><plugins> профиля, добавляется к плагинам основной модели; execution с тем же id объединяется с основным. Так в профиль it кладут maven-failsafe-plugin (зачем он нужен — в разделе surefire и failsafe, как писать executions — в разделе Привязка к фазе: executions).

Активация профиля: -P, activeByDefault, activation

Профиль Maven активируется тремя путями: явно ключом -P (или через <activeProfiles> в settings.xml), по умолчанию через <activeByDefault> или автоматически, когда выполнено условие <activation>: есть свойство, подходит версия JDK, ОС или существует файл. Явная деактивация -P '!id' выключает профиль, даже если его условие выполнено.

Способ Пример Когда профиль активен
Вручную mvn verify -P prod,it Профиль указан в -P (через запятую) или в <activeProfiles> файла settings.xml
Деактивация -P '!dev' или -P -dev Никогда в этом запуске, даже при выполненном условии
По умолчанию <activeByDefault>true</activeByDefault> Если в этом же POM не активирован ни один другой профиль (см. заметку ниже)
Свойство задано <property><name>ci</name></property> Задано системное или пользовательское свойство с любым значением: -Dci
Свойство не задано <property><name>!ci</name></property> Свойства ci нет
Значение свойства <property><name>env</name><value>ci</value></property> -Denv=ci; значение !ci по документации Maven — свойство не задано или его значение не ci
Версия JDK <jdk>25</jdk>, <jdk>[17,21)</jdk>, <jdk>!1.8</jdk> Maven запущен на JDK, версия которой начинается с префикса, входит в диапазон или (с !) не начинается с префикса
ОС <os><family>windows</family></os> Семейство ОС (windows, unix, mac); можно также name, arch, version
Файл <file><exists>${basedir}/local.properties</exists></file> Файл есть (exists) или отсутствует (missing)

Пример автоматической активации: профиль ci включается, когда задано свойство -Dci, а профиль legacy-jdk — на JDK от 17 включительно до 21 не включая:

<profile>
    <id>ci</id>
    <activation>
        <property>
            <name>ci</name>
        </property>
    </activation>
    <!-- static analysis plugins, coverage etc. -->
</profile>
<profile>
    <id>legacy-jdk</id>
    <activation>
        <jdk>[17,21)</jdk>
    </activation>
</profile>

Если в одном <activation> указано несколько условий, в Maven 3.2.2 и новее профиль активируется, только когда выполнены все (в более старых версиях хватало одного). Переменные окружения в Maven 3 доступны условию <property> как свойства с префиксом env. (например, env.CI). В пути <file> допустимы ${basedir}, системные свойства и переменные окружения, но не значения из <properties>. Проверяйте результат командой help:active-profiles, а не по памяти.

Неочевидный момент: activeByDefault выключается молча

Профиль с activeByDefault активен, только пока в том же POM не активирован ни один другой профиль — ключом -P или по условию. Команда mvn verify -P it из начала урока включает it и тем самым выключает dev: свойство db.url исчезает, и в фильтруемом ресурсе остаётся ${db.url}. То же произойдёт, если кто-то добавит профиль, который автоматически активируется по JDK. Надёжнее включать профиль по умолчанию отсутствием свойства: <property><name>!prod</name></property> (он активен, пока не задано -Dprod), или перечислять нужные профили явно: -P dev,it.

Нюанс: активация по свойству не видит <properties>

Условие <property> в Maven 3 проверяет системные свойства и свойства из командной строки (-D), но не значения из раздела <properties> POM. Запись <env>ci</env> в <properties> профиль с условием env=ci не включит — ни в основной модели, ни внутри другого профиля. Задавайте такие значения через -Denv=ci или файл .mvn/maven.config в корне проекта.

Профиль и ресурсы для разных окружений

Чтобы приложение получило настройки окружения, свойства профиля подставляют в фильтруемые ресурсы: профиль задаёт db.url, а Maven при копировании src/main/resources заменяет в файлах выражения ${db.url} значением из активного профиля. Как включить фильтрацию (<filtering>true</filtering>) и какие файлы ей подвергать, разобрано в разделе Раздел build: ресурсы и фильтрация.

С профилями dev и prod из раздела Как объявить профиль и включённой фильтрацией шаблон и результат выглядят так:

# src/main/resources/app.properties
app.env=${app.env}
db.url=${db.url}

# target/classes/app.properties after: mvn package
app.env=dev
db.url=jdbc:h2:mem:shop

# target/classes/app.properties after: mvn package -P prod
app.env=prod
db.url=jdbc:postgresql://db.example.com/shop

Если свойств окружений много, их держат не в POM, а в отдельных файлах фильтров: профиль задаёт <build><filters><filter>src/main/filters/prod.properties</filter></filters></build>, и значения из этого файла тоже подставляются в фильтруемые ресурсы. Помните, что результат — разные артефакты: jar для prod нельзя проверить на тестовом стенде, не пересобрав его.

Профили в settings.xml и activeProfiles

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

<settings xmlns="http://maven.apache.org/SETTINGS/1.2.0">
    <profiles>
        <profile>
            <id>company</id>
            <repositories>
                <repository>
                    <id>company-snapshots</id>
                    <url>https://nexus.example.com/repository/maven-snapshots/</url>
                </repository>
            </repositories>
        </profile>
    </profiles>
    <activeProfiles>
        <activeProfile>company</activeProfile>
    </activeProfiles>
</settings>

Id из <activeProfiles> активирует профиль с таким именем при каждом запуске Maven на этой машине, как если бы его передали в -P. Всё, что влияет на результат сборки, держите в pom.xml, иначе у коллег и на CI проект соберётся по-другому. Остальное устройство settings.xml (зеркала, логины, путь к репозиторию) — в разделе settings.xml: зеркала, логины и путь к репозиторию.

Какие профили активны: help:active-profiles

Узнать, какие профили Maven реально применил, можно командой mvn help:active-profiles: для каждого модуля она выводит активные профили и источник каждого (POM или settings.xml). Полный список объявленных профилей с признаком активности даёт mvn help:all-profiles, а итоговую модель с применёнными профилями — mvn help:effective-pom с теми же ключами -P.

Примерный вид для модуля, родитель которого объявляет dev с activeByDefault:

mvn help:active-profiles -pl shop-web

Active Profiles for Project 'com.examclouds:shop-web:jar:1.0-SNAPSHOT':

The following profiles are active:

 - dev (source: com.examclouds:shop-parent:1.0-SNAPSHOT)

Для help:all-profiles примерный вид (формат зависит от версии maven-help-plugin):

mvn help:all-profiles -N

[INFO] Listing Profiles for Project: com.examclouds:shop-parent:pom:1.0-SNAPSHOT
  Profile Id: dev (Active: true, Source: pom)
  Profile Id: prod (Active: false, Source: pom)
  Profile Id: e2e (Active: false, Source: pom)

Чтобы проверить, что даст профиль, не запуская сборку, сравните mvn help:effective-pom и mvn help:effective-pom -P prod. Профиль, указанный в -P, но не найденный ни в одном POM, Maven 3.9.x отмечает предупреждением вида The requested profile "prd" could not be activated because it does not exist. — частая опечатка в CI-скриптах, которая не роняет сборку.

Профили Maven и Spring profiles

Профили Maven и профили Spring — разные механизмы с одинаковым названием: профиль Maven действует во время сборки и меняет сам артефакт, а профиль Spring действует при запуске приложения и выбирает конфигурацию внутри одного и того же артефакта. Их можно связать, но заменять один другим не стоит.

Признак Профиль Maven Профиль Spring
Когда действует При сборке (mvn package) При запуске приложения
Где описан <profiles> в pom.xml или settings.xml application-{profile}.properties, аннотация @Profile
Как включить -P prod, условие <activation> spring.profiles.active=prod, переменная SPRING_PROFILES_ACTIVE
Результат Для каждого окружения свой артефакт Один артефакт, конфигурация выбирается на месте

Для настроек окружения (адреса, логины, уровни логирования) обычно удобнее профили Spring или переменные окружения: один и тот же jar проходит тестовый стенд и уходит в прод. Профили Maven оставляют для того, что действительно меняет сборку: состав модулей, плагины проверок, зависимости под конкретную JDK.

Почему не хранить пароли в профилях

Пароли, токены и другие секреты не стоит класть в профили pom.xml: файл хранится в Git, а при mvn deploy публикуется в репозиторий артефактов вместе со всеми профилями. Если секрет ещё и подставляется фильтрацией в ресурсы, он оказывается внутри собранного jar.

Подводный камень: профиль prod с паролем уходит в репозиторий

Строка <db.password>secret</db.password> в профиле prod видна всем, у кого есть доступ к Git, и всем, кто скачивает ваш POM из Nexus или Maven Central. Удалить её из истории Git и из опубликованных версий гораздо сложнее, чем не добавлять. Пароль базы приложение должно получать при запуске (переменная окружения, хранилище секретов), а учётные данные для репозиториев Maven — из <servers> в settings.xml или из секретов CI.

Частые ошибки с профилями

Большинство проблем с профилями Maven молчаливые: сборка проходит, но не с теми настройками. Поэтому при любом сомнении первым делом запускайте help:active-profiles с теми же ключами, что и сборку.

Симптом Причина Как исправить
Профиль по умолчанию «пропал» после добавления -P activeByDefault выключается, когда активирован любой другой профиль того же POM Активировать по <property><name>!...</name></property> или перечислять профили явно
Профиль с условием <property> не включается, хотя свойство есть в <properties> Условие в Maven 3 видит только системные свойства и -D Передать свойство через -D (-Denv=ci) или записать в .mvn/maven.config
Профиль не включился, сборка прошла, в логе could not be activated because it does not exist Опечатка в -P или профиль объявлен в другом POM Сверить id с help:all-profiles
Профиль с двумя условиями в <activation> не срабатывает С Maven 3.2.2 нужны все условия сразу, а не одно Разделить на два профиля или выполнить оба условия
В ресурсе осталась строка ${db.url} Профиль со свойством не активен или для каталога не включена фильтрация Проверить help:active-profiles и <filtering>true</filtering>
Свойство из профиля не применилось, хотя профиль активен То же свойство передано через -D: пользовательское свойство приоритетнее Убрать -D из команды или CI-скрипта
Каталог исходников из профиля игнорируется, Maven сообщает о нераспознанном элементе sourceDirectory и другие каталоги нельзя задавать в профиле (предупреждение или ошибка — зависит от версии) Задать каталог в основном <build> или подключить исходники плагином
На проде работает сборка, проверенная на тесте, но с другим поведением Артефакты собраны с разными -P и отличаются содержимым Выносить настройки окружения из сборки в конфигурацию запуска

Часто задаваемые вопросы

Как включить профиль Maven в IntelliJ IDEA?

В окне Maven раскройте узел Profiles и отметьте нужные профили флажками: IDEA передаёт их при импорте проекта и при запуске целей из этого окна. Профили, активные по условию, IDEA определяет сама. В конфигурации запуска Maven список профилей тоже можно задать вручную, как ключ -P.

Может ли один профиль включить другой?

Нет. Свойство из <properties> профиля не активирует другой профиль: условие <property> видит только системные свойства и -D (см. заметку в разделе Активация профиля). Если два профиля нужны вместе, дайте им общее условие, например одно свойство -Dci, или перечисляйте оба: -P ci,it.

Действуют ли профили родительского POM в модулях?

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

Что приоритетнее: -Ddb.url или свойство из профиля?

Значение из командной строки. Пользовательское свойство -Ddb.url=... перекрывает и <properties> POM, и свойства активного профиля, поэтому забытый -D в CI-скрипте может молча отменить настройку профиля.

Как посмотреть, что изменит профиль, не запуская сборку?

Сравните итоговые модели: mvn help:effective-pom -Doutput=base.xml и mvn help:effective-pom -P prod -Doutput=prod.xml, затем любой утилитой сравнения файлов. Разница — ровно то, что добавляет профиль: свойства, зависимости, плагины, модули.

Практика по теме

Закрепите урок на задачах — у каждой есть уровень и оценка времени.

Все задачи модуля →

Комментарии

Зарегистрируйтесь или войдите, чтобы иметь возможность оставить комментарий.