Unterschied zwischen Maven Scope Compile und JAR Packaging

260

Was ist der Unterschied zwischen dem Maven-Bereich compileund provideddem Artefakt, der als JAR erstellt wird? Wenn es WAR wäre, würde ich verstehen - das Artefakt wäre in WEB-INF / lib enthalten oder nicht. Bei einer JAR spielt dies jedoch keine Rolle - Abhängigkeiten sind nicht enthalten. Sie müssen sich im Klassenpfad befinden, wenn ihr Gültigkeitsbereich compileoder ist provided. Ich weiß, dass providedAbhängigkeiten nicht transitiv sind - aber ist es nur ein Unterschied?

emstol
quelle

Antworten:

289

Aus dem Maven Doc :

  • kompilieren

    Dies ist der Standardbereich, der verwendet wird, wenn keiner angegeben ist. Kompilierungsabhängigkeiten sind in allen Klassenpfaden eines Projekts verfügbar. Darüber hinaus werden diese Abhängigkeiten an abhängige Projekte weitergegeben.

  • unter der Voraussetzung

    Dies ähnelt dem Kompilieren, zeigt jedoch an, dass Sie erwarten, dass das JDK oder ein Container die Abhängigkeit zur Laufzeit bereitstellt. Wenn Sie beispielsweise eine Webanwendung für die Java Enterprise Edition erstellen, legen Sie die Abhängigkeit von der Servlet-API und den zugehörigen Java EE-APIs auf den bereitgestellten Bereich fest, da der Webcontainer diese Klassen bereitstellt. Dieser Bereich ist nur im Kompilierungs- und Testklassenpfad verfügbar und nicht transitiv.

Rekapitulieren:

  • Abhängigkeiten sind nicht transitiv (wie Sie erwähnt haben)
  • Der bereitgestellte Bereich ist nur für den Kompilierungs- und Testklassenpfad verfügbar, während der Kompilierungsbereich für alle Klassenpfade verfügbar ist.
  • vorausgesetzt, Abhängigkeiten werden nicht gepackt
Jacob
quelle
5
Ja, ich weiß. Aber ich denke über Unterschiede in den Bereichen im JAR packagingKontext nach. Maven Doc erwähnt es nicht. Ich benutze Maven für eine Weile, aber ich habe mich gerade schon danach gefragt :) Es scheint also, dass es im JAR packagingKontext keinen Unterschied zwischen compileund gibt provided(außer dem Abhängigkeitsübergang). Habe ich recht?
Emstol
3
@Jacob was ist mit "während der Kompilierungsbereich in allen Klassenpfaden verfügbar ist" gemeint ?
Geek
1
Ich denke, "NOT Transitive" ist hier der große Haken. Da die Hölle der Abhängigkeit etwas ist, mit dem Entwickler sehr häufig konfrontiert sind und der bereitgestellte Umfang dies verhindert und das Durcheinander mit anderen Versionen von entscheidender Bedeutung ist.
Seetharamani Tmr
2
Ich denke, der Unterschied liegt in der Verpackungsphase. Beim Kompilieren wird das JAR in Final War oder JAR (z. B. Spring Boot Executable JAR) eingeschlossen, und die angegebenen Ergebnisse werden möglicherweise nicht angezeigt. Da das bereitgestellte JAR möglicherweise von einem Webcontainer bereitgestellt wird (z. B. im Ordner ext lib), befindet es sich nicht im Kriegspaket, wenn es nicht von anderen Bereichen, Kompilierung und Laufzeit abhängig ist.
Addo Zhang
1
@emstol Zurück zu Ihrer ursprünglichen Frage, Sie haben Recht, dass im Fall von JAR die Abhängigkeiten nicht in der JAR selbst gepackt sind. In Maven bedeutet eine JAR-Verpackung jedoch, dass sie als Bibliothek verwendet werden soll. Sobald Sie es in ein anderes Maven-Projekt importieren, werden die transitiven Abhängigkeiten angezeigt, wenn der Bereich vorhanden ist, compileund nicht, wenn der Bereich vorhanden ist provided.
LeoLuz
291

Kompilieren bedeutet, dass Sie die JAR zum Kompilieren und Ausführen der App benötigen. Bei einer Webanwendung wird die JAR beispielsweise im Verzeichnis WEB-INF / lib abgelegt.

Vorausgesetzt, Sie benötigen die JAR zum Kompilieren, aber zur Laufzeit wird bereits eine JAR von der Umgebung bereitgestellt, sodass Sie sie nicht mit Ihrer App verpackt benötigen. Für eine Web-App bedeutet dies, dass die JAR-Datei nicht im Verzeichnis WEB-INF / lib abgelegt wird.

Wenn der App-Server für eine Web-App bereits die JAR (oder deren Funktionalität) bereitstellt, verwenden Sie "bereitgestellt", andernfalls verwenden Sie "kompilieren".

Hier ist die Referenz.

Owen Cao
quelle
11
Sie beantworten die Frage des OP nicht? " Was es Unterschiede bei der Verwendung Maven Umfang der Kompilierung und zur Verfügung gestellt , wenn Artefakt wird als JAR builded ? 'Beachten Sie, dass der Autor ausdrücklich erklärt, dass er den Unterschied beim Verpacken als Krieg kennt.
Alberto
Kann ich bereitgestellt verwenden, wenn ich auf eine andere JAR verweise, die auf demselben Anwendungsserver bereitgestellt wird?
Samy Omar
1
Um klar zu sein, wird dem Klassenpfad beim mvn exec:javaAusführen keine bereitgestellte Abhängigkeit hinzugefügt , sondern eine kompilierte Abhängigkeit.
Jamie
Ich habe diese Frage gestellt - stackoverflow.com/questions/37360132/… Das Problem wurde gelöst, indem der Bereich von "bereitgestellt" auf "kompilieren" geändert wurde. Aber ich sehe keinen Unterschied zwischen jar, das mit dem "bereitgestellten" Bereich kompiliert wurde, und jar, das mit dem "kompilierten" Bereich kompiliert wurde. Können Sie erklären, warum?
Pavel_K
Lesen Sie die erste Antwort: coderanch.com/t/502091/tools/difference-maven-compile-scope
NINCOMPOOP
22

Wenn Sie vorhaben, eine einzelne JAR-Datei mit all ihren Abhängigkeiten (die typische xxxx-all.jar) zu generieren, ist der bereitgestellte Bereich von Bedeutung, da die Klassen in diesem Bereich nicht in der resultierenden JAR enthalten sind.

Weitere Informationen finden Sie unter Maven-Assembly-Plugin

jfcorugedo
quelle
7
vorausgesetzt, die Abhängigkeit ==> Die Abhängigkeit wird NICHT gepackt.
Gab
3
Die OP-Verwirrung wird klar gelöst, wenn Sie mit verpacken maven-assembly-plugin, interessant, dass die am besten bewerteten Antworten es nicht erwähnen.
Henrique G. Abreu
Ich verstehe diese Antwort nicht. Es sieht eher nach einem Kommentar aus.
Reinierpost
11
  • kompilieren

Stellen Sie diese Abhängigkeit nicht in das endgültige JAR ein, wenn es sich um ein normales JAR handelt. Fügen Sie dieses Glas jedoch in das Glas ein, wenn das letzte Glas ein einzelnes Glas ist (z. B. ein ausführbares Glas).

  • unter der Voraussetzung

Die Abhängigkeit ist zur Laufzeitumgebung verfügbar. Fügen Sie diese Abhängigkeit daher auf keinen Fall hinzu. auch nicht in einem einzigen Glas (dh ausführbaren Glas usw.)

Vijay
quelle
3

Bei einer JAR-Datei liegt der Unterschied im Klassenpfad, der in der im JAR enthaltenen Datei MANIFEST.MF aufgeführt ist, wenn addClassPath in der Konfiguration des Maven-JAR-Plugins auf true gesetzt ist. Abhängigkeiten zum Kompilieren werden im Manifest angezeigt, vorausgesetzt, Abhängigkeiten werden nicht angezeigt.

Eines meiner Lieblingsprobleme ist, dass diese beiden Wörter dieselbe Zeitform haben sollten. Entweder kompiliert und bereitgestellt oder kompiliert und bereitgestellt.

Rick
quelle
0

Wenn Sie den Maven-Bereich als festlegen provided, bedeutet dies, dass beim Ausführen des Plugins die tatsächlich verwendete Abhängigkeitsversion von der von Ihnen installierten Version von Apache Maven abhängt.

Vishwa Ratna
quelle
0

Wenn die JAR-Datei wie die ausführbare Spring-Boot-JAR-Datei ist, müssen alle Abhängigkeiten compilealle JAR-Dateien enthalten.

Wenn die JAR-Datei jedoch in anderen Paketen oder Anwendungen verwendet wird, müssen nicht alle Abhängigkeiten in die JAR-Datei aufgenommen werden, da diese Pakete oder Anwendungen selbst andere Abhängigkeiten bereitstellen können.

Ali
quelle