Разница между компиляцией области maven и предоставленной для JAR-упаковки

260

В чем разница между областью maven compileи тем, providedкогда артефакт создается как JAR? Если бы это была WAR, я бы понял - артефакт будет включен или нет в WEB-INF / lib. Но в случае JAR это не имеет значения - зависимости не включены. Они должны быть на пути к классам, когда их область действия compileили provided. Я знаю, что providedзависимости не транзитивны - но это только одно различие?

emstol
источник

Ответы:

289

Из Maven Doc :

  • компиляции

    Это область по умолчанию, используемая, если ни одна не указана. Зависимости компиляции доступны во всех classpath проекта. Кроме того, эти зависимости распространяются на зависимые проекты.

  • при условии

    Это очень похоже на компиляцию, но указывает, что вы ожидаете, что JDK или контейнер предоставят зависимость во время выполнения. Например, при создании веб-приложения для Java Enterprise Edition вы должны установить зависимость от API-интерфейса сервлета и связанных API-интерфейсов Java EE, так как веб-контейнер предоставляет эти классы. Эта область доступна только в пути к классам компиляции и тестирования и не является транзитивной.

Резюме:

  • зависимости не являются переходными (как вы упомянули)
  • предоставленная область доступна только для пути к классам компиляции и тестирования, тогда как область компиляции доступна для всех путей к классам.
  • при условии, что зависимости не упакованы
Иаков
источник
5
Да, я знаю. Но я размышляю о различиях в JAR packagingконтексте. Maven Doc не упоминает об этом. Некоторое время я использую Maven, но я уже об этом спрашивал себя :) Так что, похоже, в JAR packagingконтексте нет никакой разницы между compileи provided(кроме перехода зависимости). Я прав?
Эмстол
3
@Jacob, что подразумевается под "тогда как область компиляции доступна во всех classpath ."?
Компьютерщик
1
Я думаю, что «НЕ переходный» является большим подвохом здесь. Потому что ад зависимостей - это то, с чем очень часто сталкиваются разработчики, а предоставляемая сфера действия предотвращает его распространение, и беспорядок в других версиях имеет решающее значение.
Seetharamani Tmr
2
Я думаю, что разница на этапе упаковки. При компиляции он будет включать jar в финальной войне или jar (например, исполняемый файл jar с загрузочной пружиной), и при условии, что это может привести к результатам. Поскольку предоставленный jar-файл может быть предоставлен веб-контейнером (например, помещенным в папку ext lib), он не находится в пакете war, если он не зависит от других областей, compile, runtime.
Аддо Чжан
1
@emstol Возвращаясь к исходному вопросу, вы правы в том, что в случае JAR зависимости не упаковываются внутри самого JAR. Но в maven JAR-упаковка означает, что вы хотите, чтобы она использовалась в качестве библиотеки. Как только вы импортируете его в какой-то другой проект maven, переходные зависимости будут перенесены, если он есть, compileи не будет, если он есть provided.
LeoLuz
291

Компиляция означает, что вам нужен JAR для компиляции и запуска приложения. Например, для веб-приложения JAR будет помещен в каталог WEB-INF / lib.

Предоставленный означает, что вам нужен JAR для компиляции, но во время выполнения уже существует JAR, предоставленный средой, поэтому вам не нужно, чтобы он был включен в ваше приложение. Для веб-приложения это означает, что файл JAR не будет помещен в каталог WEB-INF / lib.

Для веб-приложения, если сервер приложений уже предоставляет JAR (или его функциональные возможности), тогда используйте «предоставленный», иначе используйте «compile».

Вот ссылка.

Оуэн Цао
источник
11
Вы не отвечаете на вопрос ОП? « Какая разница в использовании maven scope compile и предоставляется, когда артефакт создается как JAR ? «Обратите внимание, что автор недвусмысленно заявляет, что они знают разницу при упаковке как войны.
Альберто
я могу использовать предоставленный, если я ссылаюсь на другой JAR, развернутый на том же сервере приложений ??
Сами Омар
1
Таким образом, чтобы быть ясным, предоставляемая зависимость не добавляется в mvn exec:javaпуть к классам при запуске, но скомпилированная зависимость есть.
Джейми
Я задал этот вопрос - stackoverflow.com/questions/37360132/… Проблема была решена путем изменения области действия с предоставленной для компиляции. Но я не вижу никакой разницы между jar, скомпилированным с "предоставленной" областью, и jar скомпилированной с "compile" областью действия. Не могли бы вы объяснить, почему?
Pavel_K
Прочитайте первый ответ: coderanch.com/t/502091/tools/difference-maven-compile-scope
NINCOMPOOP
22

Если вы планируете сгенерировать один файл JAR со всеми его зависимостями (типичный xxxx-all.jar), тогда предоставленная область имеет значение, потому что классы внутри этой области не будут упакованы в результирующий JAR.

Смотрите maven-assembly-plugin для получения дополнительной информации

jfcorugedo
источник
7
при условии зависимости ==> зависимость НЕ будет упакована.
Gab 是 好人
3
Путаница с ОП явно разрешается, когда вы соглашаетесь с ней maven-assembly-plugin, интересно, что в большинстве голосов, о которых идет речь, это не упоминается.
Энрике Г. Абреу
Я не понимаю этот ответ. Это больше похоже на комментарий.
reinierpost
11
  • компиляции

Сделайте доступным путь к классу, не добавляйте эту зависимость в последний jar, если это обычный jar; но добавьте этот jar в jar, если final jar - это один jar (например, исполняемый jar)

  • при условии

Зависимость будет доступна во время выполнения, поэтому ни в коем случае не добавляйте эту зависимость; даже не в одной банке (то есть исполняемой банке и т. д.)

Виджай
источник
3

Для файла jar разница заключается в пути к классам, указанном в файле MANIFEST.MF, включенном в jar, если для addClassPath задано значение true в конфигурации maven-jar-plugin. зависимости 'compile' появятся в манифесте, зависимости 'условии' не будут.

Одна из моих любимых мозолей состоит в том, что эти два слова должны иметь одинаковое время. Либо скомпилирован и предоставлен, либо скомпилирован и предоставлен.

стог
источник
0

Когда вы устанавливаете maven scope как provided, это означает, что при запуске плагина фактическая используемая версия зависимостей будет зависеть от установленной вами версии Apache Maven.

Вишва Ратна
источник
0

Если файл jar похож на исполняемый файл jar для весенней загрузки, тогда область действия всех зависимостей должна compileвключать все файлы jar.

Но если файл JAR используется в других пакетах или приложениях, то нет необходимости включать все зависимости в файл JAR, поскольку эти пакеты или приложения могут сами предоставлять другие зависимости.

Али
источник