2891 Stimmen

Wie kann ich mit Maven ein ausführbares JAR mit Abhängigkeiten erstellen?

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?

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/

2807voto

IAdapter Punkte 58848
<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>

30 Stimmen

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 .

1 Stimmen

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.

0 Stimmen

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.

408voto

André Aronsen Punkte 3861

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.

0 Stimmen

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?

331voto

Jin Kwon Punkte 18020

Siehe ausführbares-jar-mit-maven-beispiel (GitHub)

Notas

Diese Vor- und Nachteile werden dargelegt von Stephan .


Für den manuellen Einsatz

  • Profis
  • Nachteile
    • Die Abhängigkeiten sind aus dem finalen Jar heraus.

Kopieren von Abhängigkeiten in ein bestimmtes Verzeichnis

<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>

Das Jar ausführbar und klassenpfadbewusst machen

<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

Verteilbare Archive erstellen

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/* .


Apache Maven Assembly Plugin

  • Profis
  • Nachteile

    • Keine Unterstützung für Klassenverschiebung (verwenden Sie maven-shade-plugin, wenn Klassenverschiebung erforderlich ist).

    <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 .


Apache Maven Shade Plugin

  • Profis
  • 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 .


onejar-maven-plugin

  • Profis
  • Nachteile

    • Seit 2012 nicht mehr aktiv unterstützt.

    <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>


Spring Boot Maven-Plugin

  • Profis
  • Nachteile

    • Hinzufügen potenziell überflüssiger Spring- und Spring Boot-bezogener Klassen.

    <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 .

3 Stimmen

Dieses äußerst hilfreiche Standbild

0 Stimmen

Gibt es eine Möglichkeit, die Paketphase Batch- und Bash-Skript zum endgültigen Zip hinzuzufügen, so dass das Skript java -jar <was auch immer> aufrufen kann und ich nur auf das Skript verweise?

158voto

Matthew McCullough Punkte 16494

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>

0 Stimmen

In meinem Fall war maven-assembly-plugin ausreichend. danke

103voto

Vijay Katam Punkte 1271

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.com

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.

Powered by:

X