Bauen eines fetten Glases mit Maven

118

Ich habe eine Codebasis, die ich als jar verteilen möchte. Es hängt auch von externen Gläsern ab, die ich im letzten Glas bündeln möchte.

Ich habe gehört, dass dies mit gemacht werden kann maven-assembly-plug-in, aber ich verstehe nicht wie. Könnte mich jemand auf einige Beispiele hinweisen.

Im Moment benutze ich ein fettes Glas, um das letzte Glas zu bündeln. Ich möchte dasselbe mit Maven erreichen.

Bianca
quelle

Antworten:

143

Hinweis: Wenn Sie eine Spring-Boot-Anwendung sind, lesen Sie das Ende der Antwort

Fügen Sie Ihrem Plugin folgendes Plugin hinzu. pom.xml Die neueste Version finden Sie unter

...
<build>
    <plugins>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-assembly-plugin</artifactId>
            <version>CHOOSE LATEST VERSION HERE</version>
            <configuration>
                <descriptorRefs>
                    <descriptorRef>jar-with-dependencies</descriptorRef>
                </descriptorRefs>
            </configuration>
            <executions>
                <execution>
                    <id>assemble-all</id>
                    <phase>package</phase>
                    <goals>
                        <goal>single</goal>
                    </goals>
                </execution>
            </executions>
        </plugin>
    </plugins>
</build>
...

Nach der Konfiguration dieses Plug- mvn packageIns werden beim Ausführen zwei Jars erstellt: eines enthält nur die Projektklassen und ein zweites Fat Jar mit allen Abhängigkeiten mit dem Suffix "-jar-with-dependencies".

Wenn Sie classpathzur Laufzeit ein korrektes Setup wünschen, fügen Sie auch das folgende Plugin hinzu

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

Verwenden Sie für Spring Boot-Anwendungen nur das folgende Plugin (wählen Sie die entsprechende Version aus).

<plugin>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-maven-plugin</artifactId>
    <configuration>
        <fork>true</fork>
        <mainClass>${start-class}</mainClass>
    </configuration>
    <executions>
        <execution>
            <goals>
                <goal>repackage</goal>
            </goals>
        </execution>
    </executions>
</plugin>
Jigar Joshi
quelle
1
Aktuelle Version dieses Plugins ist jetzt 2.4
Guerda
13
Dies ist jetzt veraltet und das Maven-Shade-Plugin sollte stattdessen verwendet werden. Siehe @ phlogratos Antwort: stackoverflow.com/a/16222965/274350 .
Richard Neish
2
Kann das Maven-Assembly-Plugin die Größe des Fettgefäßes minimieren?
12. Mai
1
@ Richard Wo sehen Sie, dass es veraltet ist? Ich konnte hier nichts finden maven.apache.org/plugins/maven-assembly-plugin
user3833308
3
@ user3833308 "veraltet" ist möglicherweise das falsche Wort, aber in der Dokumentation unter maven.apache.org/plugins/maven-assembly-plugin heißt es: "Wenn Ihr Projekt Ihr Artefakt in einem Uber-Jar verpacken möchte, bietet das Assembly-Plugin nur grundlegende Informationen Unterstützung. Verwenden Sie für mehr Kontrolle das Maven Shade Plugin. "
Richard Neish
55

Sie können das Maven-Shade-Plugin verwenden .

Nach dem Konfigurieren des Shadow-Plugins in Ihrem Build erstellt der Befehl mvn packageein einzelnes JAR mit allen darin zusammengeführten Abhängigkeiten.

Phlogratos
quelle
9
Dies ist jetzt der richtige Weg. In der Dokumentation zum Maven-Assembly-Plugin heißt es: "Wenn Ihr Projekt Ihr Artefakt in einem Uber-Jar verpacken möchte, bietet das Assembly-Plugin nur grundlegende Unterstützung. Verwenden Sie für mehr Kontrolle das Maven Shade Plugin."
Richard Neish
Aber wie nehme ich diese einzelne .jar und verwende sie zum Veröffentlichen?
DanGordon
42

Vielleicht möchten Sie maven-shade-pluginAbhängigkeiten bündeln, nicht verwendeten Code minimieren und externe Abhängigkeiten ausblenden, um Konflikte zu vermeiden.

<build>
    <plugins>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-shade-plugin</artifactId>
            <version>3.1.1</version>
            <executions>
                <execution>
                    <phase>package</phase>
                    <goals>
                        <goal>shade</goal>
                    </goals>
                    <configuration>
                        <minimizeJar>true</minimizeJar>
                        <createDependencyReducedPom>true</createDependencyReducedPom>
                        <dependencyReducedPomLocation>
                            ${java.io.tmpdir}/dependency-reduced-pom.xml
                        </dependencyReducedPomLocation>
                        <relocations>
                            <relocation>
                                <pattern>com.acme.coyote</pattern>
                                <shadedPattern>hidden.coyote</shadedPattern>
                            </relocation>
                        </relocations>
                    </configuration>
                </execution>
            </executions>
        </plugin>
    </plugins>
</build>

Verweise:

ggrandes
quelle
Wenn man auf Provider org.apache.xerces.jaxp.SAXParserFactoryImpl not foundetwas stößt , einfach entfernen <minimizeJar>true</minimizeJar>.
Koppor
Wenn Sie die Ausnahme "java.lang.SecurityException: Ungültiger Signaturdatei-Digest für Manifest-Hauptattribute" erhalten, hilft dieser Zusatz zum obigen Konfigurationsabschnitt: stackoverflow.com/a/6743609/38368
Danny Varod
12

eigentlich das Hinzufügen der

<archive>
   <manifest>
    <addClasspath>true</addClasspath>
    <packageName>com.some.pkg</packageName>                     
    <mainClass>com.MainClass</mainClass>
  </manifest>
</archive>

Durch die Deklaration an das maven-jar-plugin wird der Hauptklasseneintrag für mich nicht zur Manifestdatei hinzugefügt. Ich musste es dem Maven-Assembly-Plugin hinzufügen, um es in das Manifest zu bekommen

ameet chaubal
quelle
5

Sie können das onejar-maven-Plugin zum Verpacken verwenden. Grundsätzlich werden Ihr Projekt und seine Abhängigkeiten in einem JAR zusammengefasst, einschließlich nicht nur Ihrer Projekt-JAR-Datei, sondern auch aller externen Abhängigkeiten als "JAR-JAR", z

<build>
    <plugins>
        <plugin>
            <groupId>com.jolira</groupId>
            <artifactId>onejar-maven-plugin</artifactId>
                <version>1.4.4</version>
                <executions>
                    <execution>
                        <goals>
                            <goal>one-jar</goal>
                        </goals>
                    </execution>
                </executions>
        </plugin>
    </plugins>
</build>

Anmerkung 1: Konfigurationsoptionen bei der Projekt zur Verfügung Homepage .

Hinweis 2: Aus dem einen oder anderen Grund wird das onejar-maven-plugin-Projekt nicht in Maven Central veröffentlicht. Allerdings jolira.com verfolgt das ursprüngliche Projekt und veröffentlicht es mit dem groupId com.jolira.

matsev
quelle
Ist es möglich, Abhängigkeiten auszuwählen, mit denen Sie verpacken möchten? Wenn beispielsweise a.jar und b.jar externe Gläser sind und ich nur a.jar in das endgültige Glas verpacken möchte, ist dies möglich / konfigurierbar?
Bianca
Ich sehe auch, dass Ein-Glas-Sachen auch im letzten Glas gebündelt wurden. Dies vergrößerte das endgültige Glas sehr. Ist es möglich, externe Gläser auszuwählen, die Sie in das endgültige Glas aufnehmen möchten? Hier ist die Ein-Glas-Protokolle: pastebin.com/UwniQJ2X
bianca
Ich weiß nicht, ob Sie konfigurieren können, was enthalten ist oder nicht. Grundsätzlich enthält ein JAR alle Abhängigkeiten, die von Ihrem Projekt angegeben werden, einschließlich der transitiven Abhängigkeiten. Ja, das endgültige JAR wird wahrscheinlich groß, wenn Sie viele Abhängigkeiten haben. Ein JAR wird etwas Overhead hinzufügen, damit Java mit der Struktur "jar of jars" funktioniert.
Matsev
2

Eine Alternative ist die Verwendung des Maven Shade Plugins zum Erstellen eines uber-jar.

<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-shade-plugin</artifactId>
    <version> Your Version Here </version>
    <configuration>
            <!-- put your configurations here -->
    </configuration>
    <executions>
            <execution>
                    <phase>package</phase>
                    <goals>
                            <goal>shade</goal>
                    </goals>
            </execution>
    </executions>
</plugin>
Stanislav
quelle