1. Обзор
В этом руководстве мы узнаем, как создать многомодульный проект с помощью Maven.
Сначала мы обсудим, что такое многомодульный проект, и рассмотрим преимущества такого подхода. Затем мы настроим наш образец проекта. Для хорошего знакомства с Maven ознакомьтесь с этим руководством .
2. Многомодульный проект Maven
Многомодульный проект создается из POM-агрегатора, который управляет группой подмодулей. В большинстве случаев агрегатор находится в корневом каталоге проекта и должен иметь упаковку типа pom
.
Подмодули представляют собой обычные проекты Maven, и их можно создавать отдельно или с помощью агрегатора POM.
При построении проекта с помощью POM-агрегатора каждый проект с типом упаковки, отличным от pom
, приведет к построению архивного файла.
3. Преимущества использования мультимодулей
Существенным преимуществом использования этого подхода является то, что мы можем уменьшить дублирование.
Допустим, у нас есть приложение, состоящее из нескольких модулей, внешнего модуля и внутреннего модуля. Теперь представьте, что мы работаем над ними и меняем функциональность, которая влияет на них обоих. В этом случае без специализированного инструмента сборки нам пришлось бы собирать оба компонента по отдельности или писать скрипт для компиляции кода, запуска тестов и отображения результатов. Затем, когда мы получили еще больше модулей в проекте, им стало сложнее управлять и поддерживать.
В реальном мире проектам могут потребоваться определенные подключаемые модули Maven для выполнения различных операций в течение жизненного цикла сборки , для совместного использования зависимостей и профилей, а также для включения других проектов BOM .
Таким образом, при использовании мультимодулей мы можем создавать модули нашего приложения одной командой, и если порядок имеет значение, Maven сделает это за нас. Мы также можем совместно использовать огромное количество настроек с другими модулями .
4. Родительский POM
Maven поддерживает наследование таким образом, что каждый файл pom.xml имеет неявный родительский POM. Он называется Super POM и может быть расположен в двоичных файлах Maven. Эти два файла объединяются Maven и образуют эффективный POM.
Мы можем создать собственный файл pom.xml, который будет служить нам родительским проектом . Затем мы можем включить в него всю конфигурацию с зависимостями и установить его как родительский для наших дочерних модулей, чтобы они наследовали от него.
Помимо наследования, Maven предоставляет понятие агрегации. Родительский POM, использующий эту функциональность, называется агрегатным POM . По сути, этот тип POM явно объявляет свои модули в файле pom.xml.
5. Подмодули
Подмодули или подпроекты — это обычные проекты Maven, которые наследуются от родительского POM. Как мы уже знаем, наследование позволяет нам делиться конфигурацией и зависимостями с подмодулями. Однако, если мы хотим собрать или выпустить наш проект за один раз, мы должны явно объявить наши подмодули в родительском POM. В конечном счете, наш родительский POM будет родителем, а также совокупным POM.
6. Создание приложения
Теперь, когда мы понимаем подмодули и иерархию Maven, давайте создадим пример приложения, чтобы продемонстрировать их. Мы будем использовать интерфейс командной строки Maven для создания наших проектов.
Это приложение будет состоять из трех модулей, которые будут представлять:
- Основная
часть
нашего домена - Веб-
служба,
предоставляющая некоторые REST API . - Веб -
приложение
, содержащее какие-либо веб-ресурсы, ориентированные на пользователя.
Поскольку мы сосредоточимся на Maven, реализация этих сервисов останется неопределенной.
6.1. Создание родительского POM
Во-первых, давайте создадим родительский проект :
mvn archetype:generate -DgroupId=com.foreach -DartifactId=parent-project
После того, как родитель сгенерирован, мы должны открыть файл pom.xml
, расположенный в каталоге родителя, и добавить упаковку как pom
:
<packaging>pom</packaging>
Установив для упаковки тип pom
, мы заявляем, что проект будет служить родителем или агрегатором; он не будет производить дальнейших артефактов.
Теперь, когда наш агрегатор готов, мы можем сгенерировать наши подмодули.
Однако мы должны отметить, что именно здесь находится вся конфигурация для совместного использования, которая в конечном итоге будет повторно использоваться в дочерних модулях. Помимо прочего, мы можем использовать здесь dependencyManagement
или pluginManagement
.
6.2. Создание подмодулей
Поскольку наш родительский POM был назван parent-project
, нам нужно убедиться, что мы находимся в родительском каталоге, и запустить команды генерации
:
cd parent-project
mvn archetype:generate -DgroupId=com.foreach -DartifactId=core
mvn archetype:generate -DgroupId=com.foreach -DartifactId=service
mvn archetype:generate -DgroupId=com.foreach -DartifactId=webapp
Обратите внимание на используемую команду. Это то же самое, что мы использовали для родителя. Дело в том, что эти модули являются обычными проектами Maven, но Maven распознал их вложенность. Когда мы изменили каталог на parent-project
, он обнаружил, что у родителя есть упаковка типа pom,
и он соответствующим образом изменит файлы pom.xml .
В pom.xml родительского проекта
будут добавлены все подмодули внутри раздела модулей :
<modules>
<module>core</module>
<module>service</module>
<module>webapp</module>
</modules>
а в pom.xml
отдельных подмодулей он добавит родительский проект в родительский
раздел:
<parent>
<artifactId>parent-project</artifactId>
<groupId>com.foreach</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
Затем Maven успешно сгенерирует три подмодуля.
Важно отметить, что подмодули могут иметь только одного родителя. Однако мы можем импортировать множество спецификаций. Подробнее о файлах BOM можно прочитать в этой статье .
6.3. Создание проекта
Теперь мы можем собрать все три модуля одновременно. В каталоге родительского проекта мы запустим:
mvn package
Это соберет все модули. Мы должны увидеть следующий вывод команды:
[INFO] Scanning for projects...
[INFO] ------------------------------------------------------------------------
[INFO] Reactor Build Order:
[INFO] parent-project [pom]
[INFO] core [jar]
[INFO] service [jar]
[INFO] webapp [war]
...
[INFO] Reactor Summary for parent-project 1.0-SNAPSHOT:
[INFO] parent-project ..................................... SUCCESS [ 0.272 s]
[INFO] core ............................................... SUCCESS [ 2.043 s]
[INFO] service ............................................ SUCCESS [ 0.627 s]
[INFO] webapp ............................................. SUCCESS [ 0.572 s]
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
Reactor перечисляет parent-project
, но, поскольку он имеет тип pom
, он исключается, и в результате сборки создаются три отдельных файла .jar
для всех остальных модулей. При этом сборка происходит в трех из них.
Более того, Maven Reactor проанализирует наш проект и соберет его в нужном порядке. Поэтому, если наш модуль веб
-приложения зависит от модуля службы
, Maven сначала создаст службу
, а затем веб- приложение
.
6.3. Включить управление зависимостями в родительском проекте
Управление зависимостями — это механизм централизации информации о зависимостях для многомодульного родительского проекта и его дочерних элементов.
Если у вас есть набор проектов или модулей, которые наследуют общего родителя, вы можете поместить всю необходимую информацию о зависимостях в общий файл pom.xml
. Это упростит ссылки на артефакты в дочерних POM
.
Давайте взглянем на образец pom.xml
родителя :
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>5.3.16</version>
</dependency>
//...
</dependencies>
</dependencyManagement>
Объявив версию spring-core
в родительском элементе, все подмодули, которые зависят от spring-core
, могут объявить зависимость, используя только groupId
и артефактId
, и версия будет унаследована:
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
</dependency>
//...
</dependencies>
Кроме того, вы можете указать исключения для управления зависимостями в родительском pom.xml
, чтобы определенные библиотеки не наследуются дочерними модулями:
<exclusions>
<exclusion>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
</exclusion>
</exclusions>
Наконец, если дочернему модулю необходимо использовать другую версию управляемой зависимости, вы можете переопределить управляемую версию в дочернем файле pom.xml
:
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>4.3.30.RELEASE</version>
</dependency>
Обратите внимание, что в то время как дочерние модули наследуются от своего родительского проекта, родительский проект не обязательно имеет какие-либо модули, которые он объединяет. С другой стороны, родительский проект может также объединять проекты, которые не наследуются от него.
Дополнительные сведения о наследовании и агрегации см. в этой документации .
6.4. Обновление подмодулей и сборка проекта
Мы можем изменить тип упаковки
каждого субмодуля. Например, давайте изменим упаковку
модуля webapp
на WAR
, обновив файл pom.xml
:
<packaging>war</packaging>
и добавление maven-war-plugin
в список плагинов:
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-war-plugin</artifactId>
<version>3.3.2</version>
<configuration>
<failOnMissingWebXml>false</failOnMissingWebXml>
</configuration>
</plugin>
</plugins>
</build>
Теперь мы можем протестировать сборку нашего проекта с помощью команды mvn clean install
. Вывод журналов Maven должен быть примерно таким:
[INFO] Scanning for projects...
[INFO] ------------------------------------------------------------------------
[INFO] Reactor Build Order:
[INFO]
[INFO] parent-project [pom]
[INFO] core [jar]
[INFO] service [jar]
[INFO] webapp [war]
//.............
[INFO] Reactor Summary for parent-project 1.0-SNAPSHOT:
[INFO]
[INFO] parent-project ..................................... SUCCESS [ 0.272 s]
[INFO] core ............................................... SUCCESS [ 2.043 s]
[INFO] service ............................................ SUCCESS [ 0.627 s]
[INFO] webapp ............................................. SUCCESS [ 1.047 s]
7. Заключение
В этой статье мы обсудили преимущества использования мультимодулей Maven. Мы также различали обычный родительский POM Maven и совокупный POM. Наконец, мы рассмотрели, как настроить простой мультимодуль, с которым можно начать играть.
Maven — отличный инструмент, но он сложен сам по себе. Если мы хотим узнать больше подробностей о Maven, мы можем посмотреть справочник по Sonatype Maven или руководства по Apache Maven . Если мы ищем расширенные возможности использования многомодульной настройки Maven, мы можем посмотреть , как проект Spring Boot использует ее использование .
Все примеры кода, использованные в этой статье, доступны на Github .