Pertanyaan Bagaimana saya bisa membuat JAR dieksekusi dengan dependensi menggunakan Maven?


Saya ingin mengemas proyek saya dalam satu JAR dieksekusi untuk distribusi.

Bagaimana saya bisa membuat paket proyek Maven semua JAR ketergantungan ke dalam output saya JAR?


1939
2018-02-22 08:43


asal


Jawaban:


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

dan Anda menjalankannya

mvn clean compile assembly:single

Tujuan kompilasi harus ditambahkan sebelum perakitan: satu atau kode pada proyek Anda sendiri tidak termasuk.

Lihat detail selengkapnya di komentar.


Umumnya tujuan ini terkait dengan fase build untuk dieksekusi secara otomatis. Ini memastikan JAR dibangun saat mengeksekusi mvn install atau melakukan penyebaran / rilis.

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

1864
2017-12-01 10:46



Anda dapat menggunakan plugin dependensi untuk membuat semua dependensi dalam direktori terpisah sebelum fase paket dan kemudian memasukkannya ke dalam classpath dari manifes:

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

Atau gunakan ${project.build.directory}/classes/lib sebagai OutputDirectory untuk mengintegrasikan semua jar-file ke dalam toples utama, tetapi kemudian Anda perlu menambahkan kode classloading khusus untuk memuat stoples.


294
2018-06-02 03:01



Saya membuat blog tentang beberapa cara berbeda untuk melakukan ini.

Lihat Jar Eksekusi dengan Apache Maven (WordPress)

atau executable-jar-dengan-maven-example (GitHub)

Catatan

Pro dan kontra tersebut disediakan oleh Stephan.


Untuk Penerapan Manual

  • Pro
  • Cons
    • Dependensi berada di luar guci terakhir.

Salin Dependensi ke direktori tertentu

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

Jadikan Jar Executable dan Classpath Sadar

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

Pada titik ini jar sebenarnya bisa dieksekusi dengan elemen classpath eksternal.

$ java -jar target/${project.build.finalName}.jar

Buat Arsip yang Dapat Diakses

Itu jar file hanya dapat dieksekusi dengan saudara kandung ...lib/ direktori. Kita perlu membuat arsip untuk menyebarkan dengan direktori dan isinya.

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

Sekarang kamu punya target/${project.build.finalName}.(zip|tar|tar.bz2|tar.gz) yang masing-masing berisi jar dan lib/*.


Apache Maven Assembly Plugin

  • Pro
  • Cons
    • Tidak ada dukungan relokasi kelas (gunakan maven-shade-plugin jika relokasi kelas diperlukan).
<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>

Kamu punya target/${project.bulid.finalName}-jar-with-dependencies.jar.


Apache Maven Shade Plugin

  • Pro
  • Cons
<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>

Kamu punya target/${project.build.finalName}-shaded.jar.


onejar-maven-plugin

  • Pro
  • Cons
    • Tidak didukung secara aktif sejak 2012.
<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>

Plugin Spring Boot Maven

  • Pro
  • Cons
    • Tambahkan kelas Spring dan Spring Boot yang tidak perlu yang potensial.
<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>

Kamu punya target/${project.bulid.finalName}-spring-boot.jar.


134
2018-02-26 04:31



Dengan jawaban yang tidak dijawab dan memformat ulang, kami memiliki:

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

Selanjutnya, saya akan merekomendasikan menjadikan ini sebagai bagian alami dari bangunan Anda, daripada sesuatu untuk dipanggil secara eksplisit. Untuk menjadikan ini bagian integral dari build Anda, tambahkan plugin ini ke Anda pom.xml dan ikat ke package acara siklus hidup. Namun, gotcha adalah bahwa Anda perlu memanggil assembly:single tujuan jika meletakkan ini di pom.xml Anda, sementara Anda akan memanggil 'assembly: assembly' jika mengeksekusinya secara manual dari baris perintah.

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

122
2017-09-22 15:20



Gunakan maven-shade-plugin untuk mengemas semua dependensi ke dalam satu uber-jar. Ini juga dapat digunakan untuk membangun tabung yang dapat dieksekusi dengan menentukan kelas utama. Setelah mencoba menggunakan maven-assembly dan maven-jar, saya menemukan bahwa plugin ini paling sesuai dengan kebutuhan saya.

Saya menemukan plugin ini sangat berguna karena menggabungkan konten file tertentu, bukan menimpanya. Ini diperlukan ketika ada file sumber daya yang memiliki nama yang sama di seluruh stoples dan plugin mencoba untuk mengemas semua file sumber daya

Lihat contoh di bawah ini

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

91
2018-03-13 20:55



Lama menggunakan maven assembly plugin, tetapi saya tidak dapat menemukan solusi untuk masalah ini "already added, skipping". Sekarang, saya menggunakan plugin lain - onejar-maven-plugin. Contoh di bawah ini (mvn package membangun guci):

<plugin>
    <groupId>org.dstovall</groupId>
    <artifactId>onejar-maven-plugin</artifactId>
    <version>1.3.0</version>
    <executions>
        <execution>
            <configuration>
                <mainClass>com.company.MainClass</mainClass>
            </configuration>
            <goals>
                <goal>one-jar</goal>
            </goals>
        </execution>
    </executions>
</plugin>

Anda perlu menambahkan repositori untuk plugin itu:

<pluginRepositories>
    <pluginRepository>
        <id>onejar-maven-plugin.googlecode.com</id>
        <url>http://onejar-maven-plugin.googlecode.com/svn/mavenrepo</url>
    </pluginRepository>
</pluginRepositories>

15
2017-10-13 12:16



Anda dapat menggunakan maven-dependency-plugin, tetapi pertanyaannya adalah bagaimana membuat JAR yang dapat dieksekusi. Untuk melakukan itu, diperlukan perubahan berikut terhadap respons Matthew Franglen (btw, menggunakan plugin ketergantungan membutuhkan waktu lebih lama untuk membangun ketika memulai dari target bersih):

<build>
    <plugins>
        <plugin>
            <artifactId>maven-jar-plugin</artifactId>
            <configuration>
                <archive>
                    <manifest>
                        <mainClass>fully.qualified.MainClass</mainClass>
                    </manifest>
                </archive>
            </configuration>
        </plugin>
        <plugin>
            <artifactId>maven-dependency-plugin</artifactId>
            <executions>
                <execution>
                    <id>unpack-dependencies</id>
                    <phase>package</phase>
                    <goals>
                        <goal>unpack-dependencies</goal>
                    </goals>
                </execution>
            </executions>
        </plugin>
    </plugins>
    <resources>
        <resource>
            <directory>${basedir}/target/dependency</directory>
        </resource>
    </resources>
</build>

14
2018-03-11 15:12



Pilihan lain jika Anda benar-benar ingin mengemas isi JARs lain di dalam hasil tunggal Anda JAR adalah Maven Assembly plugin. Ini membongkar dan kemudian mengubah segalanya menjadi direktori melalui <unpack>true</unpack>. Kemudian Anda akan memiliki pass kedua yang membangunnya menjadi satu JAR besar.

Pilihan lainnya adalah plugin OneJar. Ini melakukan tindakan pengemasan ulang di atas semua dalam satu langkah.


13
2017-08-13 18:23