Maven ile bir kavanoza bağımlılıklar dahil etmek


353

Maven'i (2.0.9) tüm bağımlılıkları tek bir jar dosyasına dahil etmeye zorlamanın bir yolu var mı?

Bir proje var tek bir jar dosyası haline. Bağımlılıklardan gelen sınıfların da kavanoza kopyalanmasını istiyorum.

Güncelleme: Bir jar dosyasına sadece bir jar dosyası ekleyemediğimi biliyorum. Bağımlılık olarak belirtilen kavanozları açmak ve sınıf dosyaları benim kavanoz içine paketlemek için bir yol arıyorum.




2
Bir jar dosyasını maven'deki jar dosyasına nasıl ekleyebilirim?
Kush Patel

Yanıtlar:


488

Bunu, "bağımlılıklara sahip kavanoz" tanımlayıcısına sahip maven-montaj eklentisini kullanarak yapabilirsiniz. İşte bunu yapan pom.xml'larımızdan birindeki ilgili yığın:

  <build>
    <plugins>
      <!-- any other plugins -->
      <plugin>
        <artifactId>maven-assembly-plugin</artifactId>
        <executions>
          <execution>
            <phase>package</phase>
            <goals>
              <goal>single</goal>
            </goals>
          </execution>
        </executions>
        <configuration>
          <descriptorRefs>
            <descriptorRef>jar-with-dependencies</descriptorRef>
          </descriptorRefs>
        </configuration>
      </plugin>
    </plugins>
  </build>

30
attachedAmaç artık kullanılmıyor. Bunun yerine singleveya directory-singlehedefi tercih edilmelidir.
Pascal Thivent

16
directory-singleartık kullanımdan kaldırıldı.
James McMahon

14
kullanarak tek resmi üzerine önerilir web
mateuszb

42
Benim gibi yeni mvn millet sıkışmış olması durumunda, eklentiyi <project> içindeki <build> içindeki <plugins> öğesine ekleyin.
DA

10
@ Christian.tucker Hedef dizinde şu şekilde oluşturulmuş ikinci bir kavanoz var: ./target/example-0.0.1-SNAPSHOT.jar ve ./target/example-0.0.1-SNAPSHOT-jar-with-dependencies.jar
teknokrat

145

Maven 2 ile bunu yapmak için doğru yolu kullanmaktır Maven2 Meclis Plugin bir sahiptir önceden tanımlanmış tanımlayıcı dosyasını bu amaçla ve sadece komut satırında kullanabileceği:

mvn assembly:assembly -DdescriptorId=jar-with-dependencies

Bu kavanozu yürütülebilir yapmak istiyorsanız, çalıştırılacak ana sınıfı eklenti yapılandırmasına eklemeniz yeterlidir:

<plugin>
  <groupId>org.apache.maven.plugins</groupId>
  <artifactId>maven-assembly-plugin</artifactId>
  <configuration>
    <archive>
      <manifest>
        <mainClass>my.package.to.my.MainClass</mainClass>
      </manifest>
    </archive>
  </configuration>
</plugin>

Bu derlemeyi normal oluşturma işleminin bir parçası olarak oluşturmak istiyorsanız, tek veya dizin tek hedefini ( assemblyamaç SADECE komut satırından çalıştırılmalıdır) bir yaşam döngüsü aşamasına ( packagemantıklı) bağlamalısınız :

<plugin>
  <groupId>org.apache.maven.plugins</groupId>
  <artifactId>maven-assembly-plugin</artifactId>
  <executions>
    <execution>
      <id>create-my-bundle</id>
      <phase>package</phase>
      <goals>
        <goal>single</goal>
      </goals>
      <configuration>
        <descriptorRefs>
          <descriptorRef>jar-with-dependencies</descriptorRef>
        </descriptorRefs>
        ...
      </configuration>
    </execution>
  </executions>
</plugin>

configurationElemanı ihtiyaçlarınıza uyacak şekilde uyarlayın (örneğin söylendiği gibi manifest şeyler ile).


Ancak tam olarak deniyorum, ancak eklenti çalışmıyor ve düz sorunsuz yürütmek bile jar dosyası oluşturulmaz. Sıkıştığım ortak bir tuzak var mı?
posdef

6
Benim için çalışıyor ama bir arayış var. derlemeden sonra, biri proje artifactid-versiyonu ve diğeri artifactid-versiyonu-"bağımlılıklarla kavanoz" ile iki kavanoz oluşturulur. Ama sadece bir kavanozun yapılmasını istiyorum. Başka bir yolu var mı
Souvik Bhattacharya

38

Yürütülebilir bir jar dosyası yapmak istiyorsanız, ana sınıfı da ayarlamaları gerekir. Yani tam yapılandırma olmalıdır.

    <plugins>
            <plugin>
                 <artifactId>maven-assembly-plugin</artifactId>
                 <executions>
                     <execution>
                          <phase>package</phase>
                          <goals>
                              <goal>single</goal>
                          </goals>
                      </execution>
                  </executions>
                  <configuration>
                       <!-- ... -->
                       <archive>
                           <manifest>
                                 <mainClass>fully.qualified.MainClass</mainClass>
                           </manifest>
                       </archive>
                       <descriptorRefs>
                           <descriptorRef>jar-with-dependencies</descriptorRef>
                      </descriptorRefs>
                 </configuration>
         </plugin>
   </plugins>

2
Neden jar adı "bağımlılıklara sahip kavanoz" ile eklenir ?! Herhangi bir geçici çözüm var mı?
Tina J

1
@Tina J , son adda "-jar-bağımlılıklarla" son ekini hariç tutmak <appendAssemblyId>false</appendAssemblyId>için <configuration>etiketin içine ekleyebilirsiniz .
ccu


17

Yeni oluşturulan kavanozu bir <classifier>etiket kullanarak kullanabilirsiniz .

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

14

(Benim gibi) özellikle yukarıda açıklanan bağımlılıklara sahip kavanoz yaklaşımından hoşlanmıyorsanız, tercih ettiğim maven çözümü, sadece inşa ettiğiniz tek başına bir java uygulaması olsa bile, sadece bir WAR projesi oluşturmaktır:

  1. (Bağımlılık olmadan) jar dosyanızı oluşturacak normal bir maven jar projesi yapın.

  2. Ayrıca, sadece jar projenizi içeren bir maven savaş projesi (yalnızca maven-build'de bir uyarı / hatadan kaçınacak boş bir src / main / webapp / WEB-INF / web.xml dosyası ile) oluşturun. bir bağımlılık ve <module>savaş projeniz altında jar projenizi bir hale getirin . (Bu savaş projesi, tüm jar dosyası bağımlılıklarınızı bir zip dosyasına sarmak için basit bir numaradır.)

  3. Savaş dosyasını üretmek için savaş projesini oluşturun.

  4. Dağıtım adımında, .war dosyanızı * .zip olarak yeniden adlandırın ve sıkıştırmasını açın.

Artık kavanozunuz ve uygulamanızı çalıştırmak için ihtiyacınız olan tüm bağımlılıklar ile bir lib-dizininiz (istediğiniz yere taşıyabilirsiniz) olmalıdır:

java -cp 'path/lib/*' MainClass

(Sınıf yolundaki joker karakter Java-6 veya daha üstü sürümlerde çalışır)

Bu hem maven'de kurulumun daha basit olduğunu düşünüyorum (montaj eklentisi ile uğraşmanıza gerek yok) ve ayrıca uygulama yapısının daha net bir görünümünü veriyor (tüm bağımlı kavanozların sürüm numaralarını düz görünümde göreceksiniz ve her şeyi tek bir kavanoz dosyasına tıkamaktan kaçının).


Eclipse "Runnable jar olarak dışa aktar" ile aynı mıdır? Çünkü bununla "JAR ile tüm bağımlılıkları paketlemeyi" seçebilirsiniz, daha sonra tüm bağımlılıkları kavanozunuz boyunca project-lib klasöründe elde edebilirsiniz.
WesternGun

@FaithReaper - "Aynı" olabilir, bunu hiç denemedim. Ama sanırım Eclipse kullanıyorsanız, otomatik olarak oluşturulamaz , bu da otomatik bir derleme + dağıtma-boru hattı uygulamak istiyorsanız bu bir zorunluluktur . Örneğin, Jenkins-server'ın git kaynak deponuzdan ya da benzerinden derleme yapmasına izin verin.
Rop

12

http://fiji.sc/Uber-JAR alternatiflerin mükemmel bir açıklamasını sunar:

Bir uber-JAR oluşturmak için üç yaygın yöntem vardır:

  1. Gölgesiz. Tüm JAR dosyalarını paketinden çıkarın ve tek bir JAR olarak yeniden paketleyin.
    • Pro: Java'nın varsayılan sınıf yükleyicisiyle çalışır.
    • Con: Aynı yola sahip birden fazla JAR dosyasında bulunan dosyalar (örn. META-INF / services / javax.script.ScriptEngineFactory) birbirlerinin üzerine yazarak hatalı davranışa neden olur.
    • Araçlar: Maven Assembly Eklentisi, Classworlds Uberjar
  2. Gölgeli. Gölgesiz ile aynı, ancak tüm bağımlılıkların tüm paketlerini yeniden adlandırın (yani "gölgelendirin").
    • Pro: Java'nın varsayılan sınıf yükleyicisiyle çalışır. Bazı (hepsi değil) bağımlılık sürüm çakışmalarını önler.
    • Con: Aynı yola sahip birden fazla JAR dosyasında bulunan dosyalar (örn. META-INF / services / javax.script.ScriptEngineFactory) birbirlerinin üzerine yazarak hatalı davranışa neden olur.
    • Araçlar: Maven Shade Eklentisi
  3. KAVANOZLARI. Son JAR dosyası, içine gömülü olan diğer JAR dosyalarını içerir.
    • Pro: Bağımlılık sürüm çakışmalarını önler. Tüm kaynak dosyaları korunur.
    • Con: Java'nın sarılmış JAR dosyalarından sınıf yükleyebilmesi için özel bir "bootstrap" sınıf yükleyicisini bir araya getirmeniz gerekir. Sınıf yükleyici sorunlarının hata ayıklaması daha karmaşık hale gelir.
    • Araçlar: Eclipse JAR Dosya İhracatçısı, One-JAR.

1
Hizmetler ile ilgili pek doğru değil, gölge eklentisinin transformatörleri var ve bunlardan biri META-INF/servicesdizin altındaki dosyaların içeriğini birleştirmektir . Daha fazla bilgi için burada: maven.apache.org/plugins/maven-shade-plugin/examples/…
vitro

7
        <!-- Method 1 -->
        <!-- Copy dependency libraries jar files to a separated LIB folder -->
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-dependency-plugin</artifactId>
            <configuration>
                <outputDirectory>${project.build.directory}/lib</outputDirectory>
                <excludeTransitive>false</excludeTransitive> 
                <stripVersion>false</stripVersion>
            </configuration>
            <executions>
                <execution>
                    <id>copy-dependencies</id>
                    <phase>package</phase>
                    <goals>
                        <goal>copy-dependencies</goal>
                    </goals>
                </execution>
            </executions>
        </plugin>
        <!-- Add LIB folder to classPath -->
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-jar-plugin</artifactId>
            <version>2.4</version>
            <configuration>
                <archive>
                    <manifest>
                        <addClasspath>true</addClasspath>
                        <classpathPrefix>lib/</classpathPrefix>
                    </manifest>
                </archive>
            </configuration>
        </plugin>


        <!-- Method 2 -->
        <!-- Package all libraries classes into one runnable jar -->
        <plugin>
            <artifactId>maven-assembly-plugin</artifactId>
            <executions>
              <execution>
                <phase>package</phase>
                <goals>
                  <goal>single</goal>
                </goals>
              </execution>
            </executions>
            <configuration>
              <descriptorRefs>
                <descriptorRef>jar-with-dependencies</descriptorRef>
              </descriptorRefs>
            </configuration>
        </plugin>            

4

Eclipse Luna ve m2eclipse: Custom Classloader (projenize indirin ve ekleyin, sadece 5 sınıf) için kesin çözümüm: http://git.eclipse.org/c/jdt/eclipse.jdt.ui.git/plain/org. eclipse.jdt.ui / kavanoz% 20in% 20jar% 20 yükleyici / org / eclipse / jdt / internal / jarinjarloader / ; bu sınıf yükleyici tek kavanozlu sınıf yükleyicinin en iyisidir ve çok hızlıdır;

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

JIJConstants "Rsrc-Class-Path" içinde "Class-Path"
mvn clean bağımlılığı düzenleyin: copy-bağımlılık paketi
lib klasöründe bağımlılıkları olan ince bir classloader ile bir kavanoz oluşturulur

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

maven-bağımlılık-eklentisi <outputDirectory> çalışmaz, her zaman "bağımlılık" klasörüne yaz
Glaucio Southier

proje bağımlılıkları içeren bir iç klasör "bağımlılık" ile bir kavanoz oluşturmak ve MANIFEST.MF koymak
Glaucio Southier

<kaynak> <kaynak> <dizin> src / main / java </directory> <includes> <include> ** / *. java </include> <include> ** / *. özellikler </include> </ içerir > </resource> <kaynak> <dizin> src / main / resources </directory> <filtering> true </filtering> <includes> <include> ** / * </include> </includes> <targetPath> META -INF / </targetPath> </resource> <kaynak> <directory> $ {project.build.directory} / bağımlılık / </directory> <includes> <include> * .jar </include> </includes> < targetPath> lib / </targetPath> </resource> </resources>
Glaucio Southier

1
Bu cevaba dayanarak bu projeyi yarattım. Pom dosyası dışında hiçbir şeyi değiştirmeniz gerekmez: github.com/raisercostin/jarinjarloader
raisercostin 18:16


0

Bu yazı biraz eski olabilir, ancak son zamanlarda da aynı sorunu yaşadım. John Stauffer tarafından önerilen ilk çözüm iyi, ancak bu baharda çalışırken bazı problemlerim vardı. Kullandığım baharın bağımlılık kavanozları, aynı yolları ve adları paylaşan bazı özellik dosyaları ve xml-şema bildirimi var. Bu kavanozlar aynı sürümlerden gelmesine rağmen, maven-goal bağımlılıklara sahip jar , bulunan dosyanın son dosyasının bulunduğu dosyanın üzerine yazıyordu.

Sonunda, bahar kavanozları doğru özellik dosyalarını bulamadığı için uygulama başlatılamadı. Bu durumda Rop tarafından önerilen çözüm sorunumu çözdü.

Ayrıca o zamandan beri, bahar çizme projesi var. Paket hedefini aşırı yükleyen ve kendi sınıf yükleyicisini sağlayan bir maven hedefi sağlayarak bu sorunu yönetmenin çok güzel bir yolu var. Yaylı botlara bakın Referans Kılavuzu


0

Bu cevaba bir göz atın:

Java JAR dosyası olarak çalışan bir yükleyici oluşturuyorum ve WAR ve JAR dosyalarını kurulum dizinindeki uygun yerlere açması gerekiyor. Bağımlılık eklentisi, paket aşamasında kopyalama hedefi ile kullanılabilir ve Maven deposundaki (WAR dosyaları dahil) herhangi bir dosyayı indirir ve ihtiyacınız olan her yere yazar. Çıktı dizinini $ {project.build.directory} / classes olarak değiştirdim ve sonuçta normal JAR görevi dosyalarımı gayet iyi içeriyor. Daha sonra bunları çıkarabilir ve kurulum dizinine yazabilirim.

<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<executions>
    <execution>
        <id>getWar</id>
        <phase>package</phase>
        <goals>
            <goal>copy</goal>
        </goals>
        <configuration>
            <artifactItems>
                <artifactItem>
                    <groupId>the.group.I.use</groupId>
                    <artifactId>MyServerServer</artifactId>
                    <version>${env.JAVA_SERVER_REL_VER}</version>
                    <type>war</type>
                    <destFileName>myWar.war</destFileName>
                </artifactItem>
            </artifactItems>
            <outputDirectory>${project.build.directory}/classes</outputDirectory>
        </configuration>
    </execution>
</executions>


0

Teşekkürler aşağıda snippet'i POM.xml dosyasına ekledim ve Mp sorunu çözüldü ve tüm bağımlı kavanozları içeren yağ kavanoz dosyası oluştur.

<plugin>
    <artifactId>maven-assembly-plugin</artifactId>
        <executions>
            <execution>
                <phase>package</phase>
                <goals>
                    <goal>single</goal>
                </goals>
            </execution>
        </executions>
        <configuration>
            <descriptorRefs>
                <descriptorRef>dependencies</descriptorRef>
            </descriptorRefs>
        </configuration>
    </plugin>
</plugins>
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.