Перейти к основному содержимому

Многомодульный проект с Maven

· 8 мин. чтения

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 .