445 Stimmen

Einbindung von Abhängigkeiten in ein jar mit Maven

Gibt es eine Möglichkeit, Maven (2.0.9) dazu zu zwingen, alle Abhängigkeiten in eine einzige Jar-Datei aufzunehmen?

Ich habe ein Projekt, das in einer einzigen Jar-Datei erstellt wird. Ich möchte, dass die Klassen aus Abhängigkeiten auch in die Jar-Datei kopiert werden.

Aktualisierung: Ich weiß, dass ich nicht einfach eine jar-Datei in eine jar-Datei einfügen kann. Ich bin auf der Suche nach einer Möglichkeit, die Jar-Dateien, die als Abhängigkeiten angegeben sind, zu entpacken und die Klassendateien in meine Jar-Datei zu packen.

19voto

lasantha Punkte 815

Sie können das neu erstellte jar mit einer <classifier> Tag.

<dependencies>
    <dependency>
        <groupId>your.group.id</groupId>
        <artifactId>your.artifact.id</artifactId>
        <version>1.0</version>
        <type>jar</type>
        <classifier>jar-with-dependencies</classifier>
    </dependency>
</dependencies>

15voto

Rop Punkte 3182

Wenn Sie (so wie ich) nicht besonders auf die jar-with-dependencies oben beschriebenen Ansatz, die von mir bevorzugte Maven-Lösung besteht darin, einfach ein WAR-Projekt zu erstellen, auch wenn es nur eine eigenständige Java-Anwendung ist, die Sie bauen:

  1. Erstellen Sie ein normales maven jar-Projekt, das Ihre jar-Datei (ohne die Abhängigkeiten) erstellt.

  2. Richten Sie außerdem ein Maven-War-Projekt ein (mit nur einem leeren src/haupt/webapp/WEB-INF/web.xml Datei, die eine Warnung/Fehler beim Maven-Build vermeidet), die nur Ihr jar-Projekt als Abhängigkeit hat, und machen Sie Ihr jar-Projekt zu einer <module> unter Ihrem Kriegsprojekt. (Dieses war-project ist nur ein einfacher Trick, um alle Ihre jar-Datei-Abhängigkeiten in eine zip-Datei zu packen).

  3. Erstellen Sie das War-Projekt, um die War-Datei zu erzeugen.

  4. Im Deployment-Schritt benennen Sie Ihre .war-Datei einfach in *.zip um und entpacken sie.

Sie sollten nun ein lib-Verzeichnis (das Sie beliebig verschieben können) mit Ihrem jar und allen Abhängigkeiten haben, die Sie zum Ausführen Ihrer Anwendung benötigen:

java -cp 'path/lib/*' MainClass

(Der Platzhalter im Klassenpfad funktioniert in Java-6 oder höher)

Ich denke, dass dies sowohl einfacher in Maven einzurichten ist (keine Notwendigkeit, mit dem Assembly-Plugin herumzupfuschen), als auch eine klarere Sicht auf die Anwendungsstruktur bietet (Sie sehen die Versionsnummern aller abhängigen Jars auf einen Blick und vermeiden es, alles in eine einzige Jar-Datei zu packen).

15voto

http://fiji.sc/Uber-JAR bietet eine ausgezeichnete Erklärung der Alternativen:

Es gibt drei gängige Methoden, um ein uber-JAR zu erstellen:

  1. Unbeschattet. Entpacken Sie alle JAR-Dateien und packen Sie sie dann wieder in ein einziges JAR.
    • Pro: Funktioniert mit dem Standard-Klassenlader von Java.
    • Contra: Dateien, die in mehreren JAR-Dateien mit demselben Pfad enthalten sind (z. B., META-INF/services/javax.script.ScriptEngineFactory), überschreiben eine sich gegenseitig, was zu fehlerhaftem Verhalten führt.
    • Werkzeuge: Maven Montage Plugin, Classworlds Uberjar
  2. Schattiert. Wie unshaded, aber alle Pakete aller Abhängigkeiten umbenennen (d.h. "schattieren").
    • Pro: Funktioniert mit dem Standard-Klassenlader von Java. Vermeidet einige (nicht alle) Versionskonflikte bei Abhängigkeiten.
    • Nachteil: Dateien die in mehreren JAR-Dateien mit demselben Pfad enthalten sind (z. B., META-INF/services/javax.script.ScriptEngineFactory) überschreiben sich sich gegenseitig, was zu fehlerhaftem Verhalten führt.
    • Werkzeuge: Maven Shade Plugin
  3. JAR der JARs. Die endgültige JAR-Datei enthält die anderen darin eingebetteten JAR-Dateien.
    • Pro: Vermeidung von Versionskonflikten bei Abhängigkeiten. Alle Ressourcen-Dateien bleiben erhalten.
    • Contra: Erforderlich ist die Bündelung eines Specials "Bootstrap"-Classloader gebündelt werden, damit Java die Klassen aus den gewickelten JAR-Dateien zu laden. Das Debuggen von Classloader-Problemen wird komplexer.
    • Werkzeuge: Eclipse JAR File Exporter, One-JAR.

5voto

Meine endgültige Lösung für Eclipse Luna und m2eclipse: Custom Classloader (herunterladen und zum Projekt hinzufügen, nur 5 Klassen) : http://git.eclipse.org/c/jdt/eclipse.jdt.ui.git/plain/org.eclipse.jdt.ui/jar%20in%20jar%20loader/org/eclipse/jdt/internal/jarinjarloader/ ; Dieser Classloader ist der beste der One-Jar Classloader und sehr schnell;

<project.mainClass>org.eclipse.jdt.internal.jarinjarloader.JarRsrcLoader</project.mainClass> <project.realMainClass>my.Class</project.realMainClass>

In JIJConstants "Rsrc-Class-Path" zu "Class-Path" ändern
mvn clean dependency:copy-dependencies Paket
wird ein jar mit Abhängigkeiten im lib-Ordner mit einem Thin Classloader erstellt

<build>
    <resources>
        <resource>
            <directory>src/main/java</directory>
            <includes>
                <include>**/*.java</include>
                <include>**/*.properties</include>
            </includes>
        </resource>
        <resource>
            <directory>src/main/resources</directory>
            <filtering>true</filtering>
            <includes>
                <include>**/*</include>
            </includes>
            <targetPath>META-INF/</targetPath>
        </resource>
        <resource>
            <directory>${project.build.directory}/dependency/</directory>
            <includes>
                <include>*.jar</include>
            </includes>
            <targetPath>lib/</targetPath>
        </resource>
    </resources>
<pluginManagement>
        <plugins>

            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-jar-plugin</artifactId>
                <configuration>
                    <archive>
                        <manifest>
                            <addClasspath>true</addClasspath>
                            <mainClass>${project.mainClass}</mainClass>
                            <classpathPrefix>lib/</classpathPrefix>
                        </manifest>

                        <manifestEntries>
                            <Rsrc-Main-Class>${project.realMainClass}  </Rsrc-Main-Class>
                            <Class-Path>./</Class-Path>
                        </manifestEntries>

                    </archive>
                </configuration>
            </plugin>
<plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-dependency-plugin</artifactId>
                <executions>
                    <execution>
                        <id>copy-dependencies</id>
                        <phase>package</phase>
                        <goals>
                            <goal>copy-dependencies</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </pluginManagement>
</build>

1voto

medopal Punkte 9494

Abgesehen von Maven können Sie JAR-Bibliotheken in das Main Jar einfügen, aber Sie müssen Ihren eigenen Classloader verwenden.

Prüfen Sie dieses Projekt: Ein-JAR Linktext

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