Правильным решением является использование конфигурации <packagingExcludes>
, так как решение <scope>provided</scope>
является взломом.
Рассмотрим следующий многомодульный проект:
A
(war)
/ \
B C
(jar) (jar)
/ /
D /
(jar) /
/ | \ /
e f g
В этом многомодульном проекте для модуля A
требуются модули {B
, C
, D
}, но не {e
, f
, g
}. Однако для модулей B
и D
do требуется {e
, f
g
}, а для C
требуется {g
}.
Сначала давайте попробуем решить эту проблему с помощью подхода <scope>provided</scope>
:
Чтобы исключить {e
, f
, g
} из A
, спецификация <scope>provided</scope>
должна присутствовать в POM D
. Но подождите, B
требует {e
, f
, g
}. Поэтому, чтобы исправить это, объявления зависимостей для {e
, f
, g
} должны присутствовать также в POM B
(с <scope>provided</scope>
). Это означает, что сложность спецификации зависимости от D
должна быть перенесена в B
. Аналогично, поскольку C
зависит от {g
}, объявления зависимостей для {g
} должны присутствовать в POM C
.
При использовании решения <scope>provided</scope>
все модули B
, C
и D
должны знать, что A
не может иметь {e
, f
, g
} .
Этот подход нарушает принцип инкапсуляции и не применим в многомодульных проектах, которые имеют сложные графы зависимостей.
Во-вторых, давайте попробуем решить эту проблему с помощью подхода <packagingExcludes>
:
Чтобы исключить {e
, f
, g
} из A
, в POM A
необходимо указать следующее:
<plugin>
<artifactId>maven-war-plugin</artifactId>
<configuration>
<packagingExcludes>a*.jar,b*.jar,c*.jar</packagingExcludes>
</configuration>
</plugin>
При таком решении сложность «того, что должно быть исключено из A
», содержится только в POM A
. Это освобождает модули B
, C
и D
от необходимости заботиться об исключении транзитивных зависимостей ради A
.
Это решение поддерживает принцип инкапсуляции.