Membangun toples lemak menggunakan maven

118

Saya memiliki basis kode yang ingin saya distribusikan sebagai jar. Ini juga memiliki ketergantungan pada toples eksternal, yang ingin saya bundel di toples terakhir.

Saya mendengar bahwa ini dapat dilakukan dengan menggunakan maven-assembly-plug-in, tetapi saya tidak mengerti caranya. Bisakah seseorang menunjukkan kepada saya beberapa contoh.

Saat ini, saya menggunakan toples lemak untuk menggabungkan toples terakhir. Saya ingin mencapai hal yang sama menggunakan maven.

bianca
sumber

Jawaban:

144

Catatan: Jika Anda adalah aplikasi boot-spring, baca akhir jawaban

Tambahkan plugin berikut ke Anda pom.xml Versi terbaru dapat ditemukan di

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

Setelah mengonfigurasi plugin ini, menjalankan mvn packageakan menghasilkan dua botol: satu hanya berisi kelas proyek, dan botol lemak kedua dengan semua dependensi dengan akhiran "-jar-with-dependencies".

jika Anda ingin classpathsetup yang benar saat runtime maka tambahkan juga plugin berikut

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

Untuk aplikasi boot musim semi gunakan hanya mengikuti plugin (pilih versi yang sesuai)

<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
sumber
1
Versi saat ini dari plugin ini sekarang 2.4
guerda
13
Ini sekarang sudah tidak digunakan lagi dan maven-shade-plugin harus digunakan sebagai gantinya. Lihat jawaban @phlogratos: stackoverflow.com/a/16222965/274350 .
Richard Neish
2
Bisakah maven-assembly-plugin meminimalkan ukuran tabung lemak?
May12
1
@Richard Di mana Anda melihatnya sudah usang? Saya tidak dapat menemukan apa pun di sekitar sini maven.apache.org/plugins/maven-assembly-plugin
user3833308
3
@ user3833308 "deprecated" mungkin kata yang salah, tetapi dokumentasi di maven.apache.org/plugins/maven-assembly-plugin mengatakan "Jika proyek Anda ingin mengemas artefak Anda dalam uber-jar, plugin assembly hanya menyediakan dasar dukungan. Untuk kontrol lebih, gunakan Plugin Maven Shade. "
Richard Neish
55

Anda dapat menggunakan maven-shade-plugin .

Setelah mengonfigurasi plugin shade di build Anda, perintah mvn packageakan membuat satu jar dengan semua dependensi digabungkan ke dalamnya.

phlogratos.dll
sumber
9
Ini sekarang cara yang benar untuk melakukannya. Dokumentasi maven-assembly-plugin menyatakan: "Jika proyek Anda ingin mengemas artefak Anda dalam uber-jar, plugin assembly hanya menyediakan dukungan dasar. Untuk kontrol lebih, gunakan Maven Shade Plugin."
Richard Neish
Tapi bagaimana cara mengambil single .jar dan menggunakannya untuk penerbitan?
DanGordon
42

Mungkin Anda ingin maven-shade-plugin, menggabungkan dependensi, meminimalkan kode yang tidak digunakan, dan menyembunyikan dependensi eksternal untuk menghindari konflik.

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

Referensi:

ggrandes.dll
sumber
Jika ada yang bertemu Provider org.apache.xerces.jaxp.SAXParserFactoryImpl not found, hapus saja <minimizeJar>true</minimizeJar>.
koppor
Jika Anda mendapatkan pengecualian "java.lang.SecurityException: Intisari file tanda tangan tidak valid untuk atribut utama Manifes", maka penambahan ke bagian konfigurasi di atas ini membantu: stackoverflow.com/a/6743609/38368
Danny Varod
12

sebenarnya, menambahkan

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

deklarasi ke maven-jar-plugin tidak menambahkan entri kelas utama ke file manifes untuk saya. Saya harus menambahkannya ke maven-assembly-plugin untuk mendapatkannya di manifes

ameet chaubal
sumber
5

Anda dapat menggunakan plugin onejar-maven untuk pengemasan. Pada dasarnya, ini merakit proyek Anda dan dependensinya dalam satu jar, termasuk tidak hanya file jar proyek Anda, tetapi juga semua dependensi eksternal sebagai "jar of jars", mis.

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

Catatan 1: Opsi konfigurasi tersedia di halaman beranda proyek .

Catatan 2: Karena satu dan lain hal, proyek onejar-maven-plugin tidak dipublikasikan di Maven Central. Namun jolira.com melacak proyek asli dan menerbitkannya dengan groupId com.jolira.

matsev
sumber
Apakah mungkin untuk memilih dependensi yang ingin Anda paketkan? Misalnya, jika a.jar dan b.jar adalah stoples eksternal dan saya hanya ingin mengemas a.jar ke dalam stoples terakhir, apakah itu mungkin / dapat dikonfigurasi?
bianca
Saya juga melihat barang-barang satu botol dibundel dalam toples terakhir juga. Ini meningkatkan ukuran toples akhir banyak. Apakah mungkin untuk memilih toples eksternal yang ingin Anda masukkan ke dalam toples terakhir? Ini adalah log satu botol: pastebin.com/UwniQJ2X
bianca
Saya tidak tahu apakah Anda dapat mengonfigurasi apa yang disertakan atau tidak. Pada dasarnya, one-jar menyertakan semua dependensi yang ditentukan oleh project Anda, termasuk dependensi transitif, jadi ya, toples terakhir kemungkinan besar akan menjadi besar jika Anda memiliki banyak dependensi. Beberapa biaya tambahan akan ditambahkan oleh satu botol, agar Java dapat bekerja dengan struktur "toples".
matsev
2

Alternatifnya adalah dengan menggunakan plugin maven shade untuk membuat file 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
sumber