Ich möchte mein Projekt in ein einziges ausführbares JAR-Paket verpacken, um es zu verteilen.
Wie kann ich ein Maven-Projekt dazu bringen, alle abhängigen JARs in mein Ausgabe-JAR zu packen?
Ich möchte mein Projekt in ein einziges ausführbares JAR-Paket verpacken, um es zu verteilen.
Wie kann ich ein Maven-Projekt dazu bringen, alle abhängigen JARs in mein Ausgabe-JAR zu packen?
<build>
<plugins>
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<configuration>
<archive>
<manifest>
<mainClass>fully.qualified.MainClass</mainClass>
</manifest>
</archive>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
</configuration>
</plugin>
</plugins>
</build>
und Sie führen es mit
mvn clean compile assembly:single
Das Kompilierziel sollte vor assembly:single hinzugefügt werden, da sonst der Code des eigenen Projekts nicht enthalten ist.
Weitere Einzelheiten finden Sie in den Kommentaren.
Dieses Ziel ist in der Regel an eine automatisch auszuführende Erstellungsphase gebunden. Dadurch wird sichergestellt, dass das JAR beim Ausführen von mvn install
oder eine Bereitstellung/Freigabe durchführen.
<build>
<plugins>
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<configuration>
<archive>
<manifest>
<mainClass>fully.qualified.MainClass</mainClass>
</manifest>
</archive>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
</configuration>
<executions>
<execution>
<id>make-assembly</id> <!-- this is used for inheritance merges -->
<phase>package</phase> <!-- bind to the packaging phase -->
<goals>
<goal>single</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
Danke @IAdapter. Beachte, dass du immer vorher kompilieren solltest, weil es nur das in das JAR einfügt, was in "target/classes" steht. Dadurch wird sichergestellt, dass das JAR alle Änderungen enthält, die Sie kürzlich am Quellcode vorgenommen haben. Sie sollten also etwas tun wie: mvn clean compile assembly:single
.
Ich habe das assembly:single-Ziel mit der Paketphase in der pom.xml meines Projekts verknüpft, aber es funktioniert nur, wenn ich ein mvn assembly:single von der Befehlszeile aus ausführe.
Gibt es eine Möglichkeit, wie ich die <mainClass> auf eine Klasse im Testverzeichnis verweisen kann? Ich habe eine Hauptklasse unter org.core (die Verzeichnisstruktur existiert unter main und test), aber Maven schließt nur kompilierte Klassen aus main und nicht test ein.
Sie können das dependency-plugin verwenden, um alle Abhängigkeiten in einem separaten Verzeichnis vor der Paketierungsphase zu erzeugen und dieses dann in den Klassenpfad des Manifests aufzunehmen:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<executions>
<execution>
<id>copy-dependencies</id>
<phase>prepare-package</phase>
<goals>
<goal>copy-dependencies</goal>
</goals>
<configuration>
<outputDirectory>${project.build.directory}/lib</outputDirectory>
<overWriteReleases>false</overWriteReleases>
<overWriteSnapshots>false</overWriteSnapshots>
<overWriteIfNewer>true</overWriteIfNewer>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<configuration>
<archive>
<manifest>
<addClasspath>true</addClasspath>
<classpathPrefix>lib/</classpathPrefix>
<mainClass>theMainClass</mainClass>
</manifest>
</archive>
</configuration>
</plugin>
Alternativ können Sie auch ${project.build.directory}/classes/lib
als OutputDirectory, um alle Jar-Dateien in das Haupt-Jar zu integrieren, aber dann müssen Sie benutzerdefinierten Classloading-Code hinzufügen, um die Jars zu laden.
Gibt es eine Möglichkeit, diese Methode zu verwenden, ohne eigene Klassenlader zu schreiben? Ich erhalte "ClassNotFoundException". Als ich das Assembly-Plugin verglichen habe, dachte ich, dass ich die Abhängigkeiten mit dem maven-dependency-plugin entpacken könnte. Irgendwelche Empfehlungen?
Siehe ausführbares-jar-mit-maven-beispiel (GitHub)
Diese Vor- und Nachteile werden dargelegt von Stephan .
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<executions>
<execution>
<id>copy-dependencies</id>
<phase>prepare-package</phase>
<goals>
<goal>copy-dependencies</goal>
</goals>
<configuration>
<outputDirectory>${project.build.directory}/${project.build.finalName}.lib</outputDirectory>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<configuration>
<archive>
<manifest>
<addClasspath>true</addClasspath>
<classpathPrefix>${project.build.finalName}.lib/</classpathPrefix>
<mainClass>${fully.qualified.main.class}</mainClass>
</manifest>
</archive>
</configuration>
</plugin>
Zu diesem Zeitpunkt ist die jar
mit externen Klassenpfad-Elementen tatsächlich ausführbar ist.
$ java -jar target/${project.build.finalName}.jar
El jar
Datei ist nur mit der Geschwisterdatei ausführbar ...lib/
Verzeichnis. Wir müssen Archive erstellen, die mit dem Verzeichnis und seinem Inhalt bereitgestellt werden.
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-antrun-plugin</artifactId>
<executions>
<execution>
<id>antrun-archive</id>
<phase>package</phase>
<goals>
<goal>run</goal>
</goals>
<configuration>
<target>
<property name="final.name" value="${project.build.directory}/${project.build.finalName}"/>
<property name="archive.includes" value="${project.build.finalName}.${project.packaging} ${project.build.finalName}.lib/*"/>
<property name="tar.destfile" value="${final.name}.tar"/>
<zip basedir="${project.build.directory}" destfile="${final.name}.zip" includes="${archive.includes}" />
<tar basedir="${project.build.directory}" destfile="${tar.destfile}" includes="${archive.includes}" />
<gzip src="${tar.destfile}" destfile="${tar.destfile}.gz" />
<bzip2 src="${tar.destfile}" destfile="${tar.destfile}.bz2" />
</target>
</configuration>
</execution>
</executions>
</plugin>
Jetzt haben Sie target/${project.build.finalName}.(zip|tar|tar.bz2|tar.gz)
die jeweils die jar
y lib/*
.
Nachteile
<plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-assembly-plugin</artifactId> <executions> <execution> <phase>package</phase> <goals> <goal>single</goal> </goals> <configuration> <archive> <manifest> <mainClass>${fully.qualified.main.class}</mainClass> </manifest> </archive> <descriptorRefs> <descriptorRef>jar-with-dependencies</descriptorRef> </descriptorRefs> </configuration> </execution> </executions> </plugin>
Sie haben target/${project.bulid.finalName}-jar-with-dependencies.jar
.
Nachteile
<plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-shade-plugin</artifactId> <executions> <execution> <goals> <goal>shade</goal> </goals> <configuration> <shadedArtifactAttached>true</shadedArtifactAttached> <transformers> <transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer"> <mainClass>${fully.qualified.main.class}</mainClass> </transformer> </transformers> </configuration> </execution> </executions> </plugin>
Sie haben target/${project.build.finalName}-shaded.jar
.
Nachteile
<plugin> <!--groupId>org.dstovall</groupId--> <!-- not available on the central --> <groupId>com.jolira</groupId> <artifactId>onejar-maven-plugin</artifactId> <executions> <execution> <configuration> <mainClass>${fully.qualified.main.class}</mainClass> <attachToBuild>true</attachToBuild> <!-- https://code.google.com/p/onejar-maven-plugin/issues/detail?id=8 --> <!--classifier>onejar</classifier--> <filename>${project.build.finalName}-onejar.${project.packaging}</filename> </configuration> <goals> <goal>one-jar</goal> </goals> </execution> </executions> </plugin>
Nachteile
<plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> <executions> <execution> <goals> <goal>repackage</goal> </goals> <configuration> <classifier>spring-boot</classifier> <mainClass>${fully.qualified.main.class}</mainClass> </configuration> </execution> </executions> </plugin>
Sie haben target/${project.bulid.finalName}-spring-boot.jar
.
Nimmt man die Antwort von Unanswered und formatiert sie um, ergibt sich Folgendes:
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<configuration>
<archive>
<manifest>
<addClasspath>true</addClasspath>
<mainClass>fully.qualified.MainClass</mainClass>
</manifest>
</archive>
</configuration>
</plugin>
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<configuration>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
</configuration>
</plugin>
</plugins>
</build>
Als Nächstes würde ich empfehlen, dies zu einem natürlichen Bestandteil deines Builds zu machen, anstatt es explizit zu fordern. Um dies zu einem festen Bestandteil Ihres Builds zu machen, fügen Sie dieses Plugin zu Ihrem pom.xml
und binden es an die package
Lebenszyklus-Ereignis. Ein Problem besteht jedoch darin, dass Sie die assembly:single
Ziel, wenn Sie dies in Ihre pom.xml einfügen, während Sie "assembly:assembly" aufrufen würden, wenn Sie es manuell von der Befehlszeile aus ausführen.
<project>
[...]
<build>
<plugins>
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<configuration>
<archive>
<manifest>
<addClasspath>true</addClasspath>
<mainClass>fully.qualified.MainClass</mainClass>
</manifest>
</archive>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
</configuration>
<executions>
<execution>
<id>make-my-jar-with-dependencies</id>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
</execution>
</executions>
</plugin>
[...]
</plugins>
[...]
</build>
</project>
Verwenden Sie das maven-shade-plugin, um alle Abhängigkeiten in ein uber-jar zu packen. Es kann auch verwendet werden, um ein ausführbares Jar zu erstellen, indem man die Hauptklasse angibt. Nachdem ich maven-assembly und maven-jar ausprobiert hatte, stellte ich fest, dass dieses Plugin meinen Bedürfnissen am besten entspricht.
Ich fand dieses Plugin besonders nützlich, da es den Inhalt bestimmter Dateien zusammenführt, anstatt sie zu überschreiben. Dies ist notwendig, wenn es Ressourcendateien gibt, die in allen Jars den gleichen Namen haben, und das Plugin versucht, alle Ressourcendateien zu verpacken
Siehe Beispiel unten
<plugins>
<!-- This plugin provides the capability to package the artifact in an uber-jar, including its dependencies and to shade - i.e. rename - the packages of some of the dependencies. -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>1.4</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
<configuration>
<artifactSet>
<!-- signed jars-->
<excludes>
<exclude>bouncycastle:bcprov-jdk15</exclude>
</excludes>
</artifactSet>
<transformers>
<transformer
implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
<!-- Main class -->
<mainClass>com.main.MyMainClass</mainClass>
</transformer>
<!-- Use resource transformers to prevent file overwrites -->
<transformer
implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
<resource>properties.properties</resource>
</transformer>
<transformer
implementation="org.apache.maven.plugins.shade.resource.XmlAppendingTransformer">
<resource>applicationContext.xml</resource>
</transformer>
<transformer
implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
<resource>META-INF/cxf/cxf.extension</resource>
</transformer>
<transformer
implementation="org.apache.maven.plugins.shade.resource.XmlAppendingTransformer">
<resource>META-INF/cxf/bus-extensions.xml</resource>
</transformer>
</transformers>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.
15 Stimmen
Bitte erklären Sie, auf welches Ziel des Abhängigkeits-Plugins Sie sich beziehen. Ich kenne kein Ziel, das das tut, was die ursprüngliche Frage verlangt: alle Abhängigkeiten entweder A) in das Autoren-Jar durch Umpacken zu packen, oder B) ein ausführbares Jar zu erstellen, das die anderen in einem Klassenpfad von MANIFEST.MF hat
2 Stimmen
Dies könnte für Sie nützlich sein rationaljava.com/2015/02/
1 Stimmen
2 Beispiele: tugay.biz/2015/12/a-standalone-java-web-anwendung-mit.html tugay.biz/2016/11/wie-erstelle-ich-ein-ausführbares-jar-mit.html
2 Stimmen
Siehe stackoverflow.com/questions/35217128/
0 Stimmen
Für Gradle siehe den Stackoverflow-Beitrag: Fat/Uber JAR in Gradle erstellen .