W3docs

Жизненный цикл сборки Maven

Изучите три жизненных цикла Maven и основные фазы — validate, compile, test, package, verify, install, deploy — и как цели плагинов привязываются к ним.

Жизненный цикл — центральная идея Maven: сборка проекта — это не произвольный набор задач, а упорядоченная последовательность хорошо известных фаз. Когда вы вводите mvn package, вы не называете одно действие — вы просите Maven выполнить каждую фазу вплоть до package включительно, по порядку. Понимание этой последовательности и того, как цели плагинов привязываются к ней, — это разница между слепым копированием команд и реальным пониманием того, что делает ваша сборка.

Три жизненных цикла, и тот, который вы используете чаще всего

Maven поставляется с тремя встроенными жизненными циклами. Они независимы — вызов фазы одного не запускает другой.

Жизненный циклНазначениеКлючевые фазы
cleanУдалить результаты сборкиpre-clean, clean, post-clean
defaultСобрать и развернуть проектvalidatecompiletestpackageinstalldeploy
siteСгенерировать документацию проектаpre-site, site, site-deploy

Жизненный цикл default — это место, где происходит основная работа. Команда mvn clean install, которую вы повсюду видите, — это просто два жизненных цикла в одной команде: фаза clean из цикла clean, а затем фаза install из цикла default.

Фазы жизненного цикла default

Жизненный цикл default состоит из 23 фаз, но семь из них несут основную нагрузку почти в каждой сборке. Они всегда выполняются в таком порядке:

ФазаЧто делает
validateПроверяет корректность проекта и наличие всей необходимой информации
compileКомпилирует исходный код проекта
testЗапускает модульные тесты с помощью подходящего фреймворка (не требует упаковки)
packageУпаковывает скомпилированный код в дистрибутивный формат, например JAR
verifyВыполняет проверки результатов интеграционных тестов для подтверждения качества
installКопирует пакет в локальный репозиторий (~/.m2) для других локальных проектов
deployЗагружает пакет в удалённый репозиторий для совместного использования

Правило, которое управляет всем: запуск фазы запускает эту фазу и все предшествующие ей. Так, mvn package незаметно сначала выполнит validate, compile и test. Нет способа «перепрыгнуть» — можно только остановиться раньше.

mvn validate     # just the sanity checks
mvn compile      # validate -> compile
mvn test         # validate -> compile -> test
mvn package      # ... -> test -> package (produces target/app-1.0.jar)
mvn install      # ... -> package -> verify -> install (now in ~/.m2)
mvn deploy       # the full pipeline, ending with an upload

Фазы пусты, пока плагины не привяжут к ним цели

Фаза — это просто имя и позиция в последовательности, она сама по себе не выполняет никакой работы. Работу выполняют цели плагинов, привязанные к фазам. Цель записывается как plugin:goal, например compiler:compile. Для проекта, у которого <packaging> равен jar, Maven предоставляет разумный набор привязок по умолчанию:

ФазаЦель по умолчанию
compilemaven-compiler-plugin:compile
testmaven-surefire-plugin:test
packagemaven-jar-plugin:jar
installmaven-install-plugin:install
deploymaven-deploy-plugin:deploy

Вы можете добавлять собственные привязки в pom.xml. Здесь плагин exec привязан к фазе verify, чтобы он автоматически запускался ближе к концу сборки:

<build>
  <plugins>
    <plugin>
      <groupId>org.codehaus.mojo</groupId>
      <artifactId>exec-maven-plugin</artifactId>
      <version>3.1.0</version>
      <executions>
        <execution>
          <id>smoke-test</id>
          <phase>verify</phase>
          <goals><goal>java</goal></goals>
        </execution>
      </executions>
    </plugin>
  </plugins>
</build>

Вы также можете вызвать цель напрямую, вне какой-либо фазы — mvn compiler:compile запускает только эту цель, полностью минуя жизненный цикл. Это иногда бывает полезно, но в повседневной работе вы вызываете фазы и позволяете привязкам срабатывать.

Практический пример: моделирование жизненного цикла

Maven сам по себе не установлен на этом исполнителе, поэтому мы моделируем жизненный цикл на чистом Java, чтобы сделать его правила конкретными. Программа перечисляет фазы по умолчанию, записывает привязанный к каждой plugin:goal, затем «запускает» mvn install — выполняя каждую фазу от validate до install и доказывая, что deploy и clean не включаются.

java— editable, runs on the server

Что следует вынести из этого запуска:

  • Вывод начинается с validate и заканчивается на install — шесть фаз для одной команды. Это накопительное правило в действии: mvn install — это сокращение для выполнения всего префикса последовательности вплоть до install, а не только одной именованной фазы.
  • Каждая выполненная фаза вывела привязанный к ней plugin:goal (compile -> compiler:compile, package -> jar:jar и так далее). Фазы — это слоты; цели — это то, что фактически компилирует, тестирует и упаковывает. validate вывела (no goal bound), показывая, что фаза может запускаться, не делая ничего.
  • deploy skipped : true подтверждает, что фазы после запрошенной никогда не выполняются. Чтобы опубликовать в удалённый репозиторий, нужно явно запросить mvn deploy; обычный install намеренно остаётся локальным.
  • clean ran : false доказывает, что clean принадлежит отдельному жизненному циклу. Вызов install не удаляет target/, именно поэтому mvn clean install явно указывает оба — по одной фазе из каждого жизненного цикла.
  • Фазы выполнялись в фиксированном порядке validate, compile, test, package, verify, install, и программа завершилась с BUILD SUCCESS. Порядок не является предметом переговоров; обещание Maven «соглашение важнее конфигурации» основано именно на этой гарантированной повторяемой последовательности.

Распространённые команды на практике

Несколько вызовов покрывают почти всю повседневную работу:

mvn clean              # delete target/
mvn test               # build and run unit tests
mvn package -DskipTests  # build the JAR without running tests
mvn clean install      # fresh build, install to local ~/.m2
mvn clean verify       # CI's favourite: build + unit + integration checks

-DskipTests компилирует тесты, но не запускает их; -Dmaven.test.skip=true также пропускает их компиляцию. Используйте первый вариант, когда тесты медленные, но должны компилироваться, второй — только когда вы действительно хотите полностью исключить их.

Что изучить дальше

  • Только знакомитесь с инструментом? Начните со введения в Maven, затем прочитайте, как POM объявляет плагины и привязки.
  • Фазы compile и package успешно выполняются только после разрешения зависимостей проекта — см. управление зависимостями.
  • Предпочитаете модель графа задач вместо фиксированной последовательности фаз? Сравните с введением в Gradle.

Практика

Практика
В стандартном Maven JAR-проекте, что делает команда 'mvn package'?
В стандартном Maven JAR-проекте, что делает команда 'mvn package'?
Was this page helpful?