«1. Обзор
В многомодульном проекте Maven эффективный POM является результатом слияния всех конфигураций, определенных в модуле и его родительских элементах.
Чтобы избежать избыточности и дублирования между модулями, мы часто храним общие конфигурации в общем родительском модуле. Однако может возникнуть проблема, если нам нужно иметь пользовательскую конфигурацию для дочернего модуля, не влияя на все его братья и сестры.
В этом уроке мы узнаем, как переопределить конфигурацию родительского плагина.
2. Наследование конфигурации по умолчанию
Конфигурации плагинов позволяют нам повторно использовать общую логику сборки в разных проектах. Если у родителя есть плагин, у дочернего он будет автоматически без дополнительной настройки. Это как наследство.
Для этого Maven объединяет файлы XML на уровне элементов. Если дочерний элемент определяет элемент с другим значением, он заменяет элемент родительского элемента. Давайте посмотрим на это в действии.
2.1. Структура проекта
Во-первых, давайте определим многомодульный проект Maven для экспериментов. Наш проект будет состоять из одного родителя и двух дочерних элементов:
+ parent
+ child-a
+ child-b
Допустим, мы хотим настроить подключаемый модуль maven-compiler для использования разных версий Java между модулями. Давайте настроим наш проект для использования Java 11 в целом, но дочерний элемент будет использовать Java 8.
Мы начнем с родительской конфигурации:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>11</source>
<target>11</target>
<maxmem>512m</maxmem>
</configuration>
</plugin>
Здесь мы указали дополнительное свойство, maxmem, которое мы также хотим использовать. Однако мы хотим, чтобы у child-a были собственные настройки компилятора.
Итак, давайте настроим child-a для использования Java 8:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
Теперь, когда у нас есть наш пример, давайте посмотрим, что он делает с эффективным POM.
2.2. Понимание эффективного POM
Эффективный POM зависит от различных факторов, таких как наследование, профили, внешние настройки и т. д. Чтобы увидеть фактический POM, давайте запустим mvn help: Effective-pom из каталога child-a:
mvn help:effective-pom
...
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>1.8</source>
<target>1.8</target>
<maxmem>512m</maxmem>
</configuration>
</plugin>
Как и ожидалось, child-a имеет свои собственные варианты исходных и целевых значений. Однако еще одним сюрпризом является то, что он также имеет свойство maxmem от своего родителя.
Это означает, что если определено какое-либо дочернее свойство, оно будет иметь преимущество, в противном случае будет использоваться родительское.
3. Расширенное наследование конфигурации
Когда мы хотим точно настроить стратегию слияния, мы можем использовать атрибуты. Эти атрибуты помещаются в XML-элемент, которым мы хотим управлять. Кроме того, они будут унаследованы и затронут только детей первого уровня.
3.1. Работа со списками
В предыдущем примере мы видели, что происходит, если дочерний элемент имеет другое значение. Теперь рассмотрим случай, когда у потомка другой список элементов. В качестве примера рассмотрим включение нескольких каталогов ресурсов с помощью плагина maven-resources-plugin.
В качестве основы давайте настроим родительский модуль для включения ресурсов из каталога parent-resources:
<plugin>
<artifactId>maven-resources-plugin</artifactId>
<configuration>
<resources>
<resource>
<directory>parent-resources</directory>
</resource>
</resources>
</configuration>
</plugin>
На этом этапе child-a унаследует эту конфигурацию плагина от своего родителя. Однако предположим, что мы хотим определить альтернативный каталог ресурсов для дочернего элемента:
<plugin>
<artifactId>maven-resources-plugin</artifactId>
<configuration>
<resources>
<resource>
<directory>child-a-resources</directory>
</resource>
</resources>
</configuration>
</plugin>
Теперь давайте рассмотрим действующий POM:
mvn help:effective-pom
...
<configuration>
<resources>
<resource>
<directory>child-a-resources</directory>
</resource>
</resources>
</configuration>
В этом случае весь список переопределяется дочерней конфигурацией. .
3.2. Append Parent Configuration
Возможно, мы хотим, чтобы некоторые дочерние элементы использовали общий каталог ресурсов, а также определяли дополнительные. Для этого мы можем добавить родительскую конфигурацию, используя combo.children=†append“ для элемента ресурсов в родительском элементе:
<resources combine.children="append">
<resource>
<directory>parent-resources</directory>
</resource>
</resources>
Следовательно, действующий POM будет содержать оба из них:
mvn help:effective-pom
....
<resources combine.children="append">
<resource>
<directory>parent-resources</directory>
</resource>
<resource>
<directory>child-a-resources</directory>
</resource>
</resources>
Атрибуты объединения не распространяются ни на какие вложенные элементы. Таким образом, если бы раздел ресурсов имел сложную структуру, вложенные элементы были бы объединены с использованием стратегии по умолчанию.
3.3. Переопределить дочернюю конфигурацию
В предыдущем примере дочерний элемент не полностью контролировал окончательный POM из-за родительской стратегии объединения. Дочерний элемент может переопределить родительский, добавив в свой элемент resources, comb.self=“override”:
<resources combine.self="override">
<resource>
<directory>child-a-resources</directory>
</resource>
</resources>
В этом случае дочерний элемент восстанавливает контроль:
mvn help:effective-pom
...
<resources combine.self="override">
<resource>
<directory>child-a-resources</directory>
</resource>
</resources>
4. Ненаследуемые плагины ~~ ~»
«Предыдущие атрибуты подходят для тонкой настройки, но они не подходят, когда дочерний элемент полностью не согласен со своим родителем.
Чтобы избежать наследования плагина вообще, мы можем добавить свойство \u003cinherited\u003efalse\u003c/inherited\u003e на родительском уровне:
<plugin>
<inherited>false</inherited>
<groupId>org.apache.maven.plugins</groupId>
...
</plugin>
Это означает, что плагин будет применен только к родительскому и не будет распространяться на его потомков.
5. Заключение
В этой статье мы увидели, как переопределить конфигурацию родительского плагина.
Сначала мы изучили поведение по умолчанию. Затем мы увидели, как родитель может определить политику слияния и как потомок может ее отклонить. Наконец, мы увидели, как пометить плагин как ненаследуемый, чтобы избежать его переопределения всеми дочерними элементами.
Как всегда, код доступен на GitHub.