У тому числі залежність в банку з Мейвен


353

Чи є спосіб змусити maven (2.0.9) включити всі залежності в один файл jar?

У мене є проект складання в один файл jar. Я хочу, щоб класи з залежностей також були скопійовані в банку.

Оновлення: Я знаю, що я не можу просто включити jar файл у jar файл. Я шукаю спосіб розпакувати банки, які вказані як залежності, і упакувати файли класу в мій jar.




2
Як включити файл jar в файл jar в Maven?
Куш Патель

Відповіді:


488

Це можна зробити, використовуючи плагін maven-Assembly з дескриптором "jar-with-зависимост". Ось відповідний фрагмент одного з наших пом.xml, який робить це:

  <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
attachedМетою є застарілим. singleАбо directory-singleмета повинна бути кращим замість цього.
Паскаль Thivent

16
directory-singleтепер також застаріло.
Джеймс Макмахон

14
використовувати сингл рекомендується на офіційному веб-сайті
mateuszb

42
Якщо будь-які нові mvn люди застрягли, як я, додайте плагін до <plugins> всередині <build>, який знаходиться в <project>.
DA

10
@ Christian.tucker В цільовому каталозі створений другий jar: ./target/example-0.0.1-SNAPSHOT.jar та ./target/example-0.0.1-SNAPSHOT-jar-with-dependitions.jar
технократ

145

З Maven 2 правильний спосіб зробити це - використовувати плагін Maven2 Assembly, який має для цього заздалегідь визначений файл дескриптора, який ви можете просто використовувати в командному рядку:

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

Якщо ви хочете зробити цю банку виконуваною, просто додайте основний клас, який слід запустити, до конфігурації плагіна:

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

Якщо ви хочете створити що збірка , як частина нормального процесу складання, ви повинні зв'язати одного або каталог синглу мети ( assemblyмета повинна тільки бути запущена з командного рядка) до фази життєвого циклу ( packageмає сенс), що - щось на зразок цього:

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

Пристосовуйте configurationелемент відповідно до ваших потреб (наприклад, з маніфестаційними матеріалами, про які говориться).


Я намагаюся саме це, однак плагін не запускається і файл jar не створюється, навіть якщо збірка виконується плавно. Чи є загальний підводний камінь, до якого я, можливо, застряг?
posdef

6
Це працює для мене, але провести квести. після збирання зараз створюються дві банки: одна з проектною артефактид-версією та друга з артефактид-версією - "jar-with-залежності". Але я хочу створити лише одну банку. Чи є інший спосіб
Сувік Бхаттачарія

38

Якщо ви хочете виконати виконуваний файл jar, їм також потрібно встановити основний клас. Отже, повна конфігурація повинна бути.

    <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
Чому назва jar додається "jar-with-зависимост" ?! Будь-які обходи?
Тіна J

1
@Tina J ви можете додати <appendAssemblyId>false</appendAssemblyId>всередині <configuration>тегу, щоб виключити суфікс "-jar-with-зависимост" у остаточному імені.
ccu

19

Там є плагін Maven Shadow . Він може використовуватися для упаковки та перейменування залежностей (щоб опустити проблеми залежності на classpath).


2
якщо вам не подобається jar-with-зависимост як частина імені файлу.
Кайл

мінімізувати функцію maven.apache.org/plugins/maven-shade-plugin/examples/…
Alex78191

це була найкраща відповідь для мене .. :)
Ананд Варкі Філіпс

17

Ви можете використовувати новостворену банку за допомогою <classifier>тегу.

<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

Якщо ви (як я) особливо не любите описаний вище підхід jar-with-зависимост , я віддаю перевагу maven-рішення - просто створити WAR-проект, навіть якщо це лише окремий Java-додаток, який ви будуєте:

  1. Створіть звичайний jar-проект Maven, який створить ваш jar-файл (без залежностей).

  2. Крім того, встановіть проект maven war (із лише порожнім src / main / webapp / WEB-INF / web.xml- файлом, що дозволить уникнути попередження / помилки в maven-build), який має лише ваш jar-проект як залежність, і зробіть свій jar-проект <module>під вашим військовим проектом. (Цей військовий проект - лише простий трюк, щоб обернути всі свої jar-файлові залежності в zip-файл.)

  3. Створіть проект війни для створення файлу війни.

  4. На етапі розгортання просто перейменуйте свій .war-файл у * .zip та розпакуйте його.

Тепер у вас повинен бути каталог lib (який ви можете переміщати куди захочете) зі своїм баночкою та всіма залежностями, необхідними для запуску програми:

java -cp 'path/lib/*' MainClass

(Заголовок підказок у класі працює на Java-6 або новіших версіях)

Я думаю, що це і простіше в налаштуванні в maven (не потрібно возитися з плагіном збирання), а також дає чіткіше уявлення про структуру додатків (ви побачите номери версій усіх залежних банок у простому вигляді, і не забивайте все в один jar-файл).


Це те саме, що у Eclipse "Експорт як рункова баночка"? Оскільки за допомогою цього ви можете вибрати "пакет усіх залежностей за допомогою JAR", то ви отримаєте всі залежності в папці "Project-lib" уздовж вашої банки.
WesternGun

@FaithReaper - Це може бути "те саме", я ніколи цього не пробував. Але я думаю, якщо ви користуєтеся Eclipse, це не просто сценарій, що є необхідною умовою, якщо ви хочете реалізувати автоматизований конвеєр + розгортання-конвеєр. Наприклад, дозвольте сервісу Jenkins робити збірку з вашого git source-сховища чи подібного.
Rop

12

http://fiji.sc/Uber-JAR пропонує чудове пояснення альтернатив:

Існує три загальних методики побудови uber-JAR:

  1. Не затінені. Розпакуйте всі файли JAR, а потім перепакуйте їх в один JAR.
    • Pro: працює з завантажувачем класу Java за замовчуванням.
    • Con: Файли, присутні в декількох файлах JAR з однаковим шляхом (наприклад, META-INF / services / javax.script.ScriptEngineFactory), перезаписують один одного, що призводить до неправомірної поведінки.
    • Інструменти: плагін для складання Maven, Classworlds Uberjar
  2. Заштриховані. Те саме, що не заштриховано, але перейменуйте (тобто "відтінок") всі пакети всіх залежностей.
    • Pro: працює з завантажувачем класу Java за замовчуванням. Уникайте деяких (не всіх) сутичок версій залежності.
    • Con: Файли, присутні в декількох файлах JAR з однаковим шляхом (наприклад, META-INF / services / javax.script.ScriptEngineFactory), перезаписують один одного, що призводить до неправомірної поведінки.
    • Інструменти: плагін Maven Shade
  3. JAR JARs. Остаточний файл JAR містить інші вбудовані файли JAR.
    • Про: уникає зіткнень версій залежності. Усі файли ресурсів зберігаються.
    • Кон: Потрібно поєднати спеціальний завантажувач класів "завантажувальний", щоб Java могла завантажувати класи з загорнутих файлів JAR. Налагодження питань завантажувача класів стає складнішим.
    • Інструменти: Експортер файлів Eclipse JAR, One-JAR.

1
Не зовсім вірно щодо послуг, сенсорний плагін має трансформатори, і один з них призначений для об'єднання вмісту файлів у META-INF/servicesкаталозі. Більше інформації тут: 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 та m2eclipse: Користувальницький завантажувач (завантажте та додайте до свого проекту, лише 5 класів): http://git.eclipse.org/c/jdt/eclipse.jdt.ui.git/plain/org. eclipse.jdt.ui / jar% 20in% 20jar% 20loader / org / eclipse / jdt / Internal / jarinjarloader / ; цей навантажувач класів є найкращим однокласником і дуже швидким;

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

Відредагуйте в JIJConstants "Rsrc-Class-Path" на "Class-Path"
mvn чиста залежність: пакет залежностей від копіювання
створюється баночкою із залежностями в папці lib з тонким завантажувачем класів

<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-зависимості <outputDirectory> не працюйте, завжди пишіть у папці "залежність"
Glaucio Southier

Створіть банку з внутрішньою папкою "залежність", що містить проектні залежності, і поставте її на MANIFEST.MF
Glaucio Southier

<resources> <resource> <directory> src / main / java </directory> <includes> <include> ** / *. java </include> <include> ** / *. властивості </include> </ включає > </resource> <resource> <directory> src / main / ресурси </directory> <filtering> true </filtering> <includes> <include> ** / * </include> </includes> <targetPath> META -INF / </targetPath> </resource> <resource> <directory> $ {project.build.directory} / залежність / </directory> <includes> <include> * .jar </include> </includes> < targetPath> lib / </targetPath> </resource> </resources>
Glaucio Southier

1
На основі цієї відповіді я створив цей проект. Вам нічого не потрібно змінювати, окрім файлу пом: github.com/raisercostin/jarinjarloader
raercostin

1

Відклавши Maven убік, ви можете помістити бібліотеки JAR всередину Main Jar, але вам потрібно буде використовувати власний завантажувач класів.

Перевірте цей проект: Текст посилання One-JAR


Існує також плагін Maven для One-JAR: onejar-maven-plugin.googlecode.com/svn/mavensite/usage.html
Тіло

0

Цей пост може бути трохи старим, але у мене теж була та сама проблема останнім часом. Перше рішення, запропоноване Джоном Штауфером, є хорошим, але у мене були деякі проблеми, коли я працюю цієї весни. Використовувані ями джерела залежності джерела мають деякі файли властивостей та декларацію xml-схем, які мають однакові шляхи та назви. Хоча ці банки виходять з одних і тих же версій, залежно від залежності maven-goal перезаписував тезовий файл з останнім знайденим файлом.

Зрештою, додаток не вдалося запустити, оскільки пружинні банки не змогли знайти правильні файли властивостей. У цьому випадку рішення, запропоноване Ропом, вирішило мою проблему.

З того часу проект весняного завантаження зараз існує. Це дуже класний спосіб вирішити цю проблему, забезпечивши мету Maven, яка перевантажує мету пакета та забезпечить власний навантажувач класу. Дивіться Посібник з весняних чобіт


0

Подивіться на цю відповідь:

Я створюю інсталятор, який працює як файл Java JAR, і йому потрібно розпакувати файли WAR та JAR у відповідні місця в каталозі інсталяції. Плагін залежності може використовуватися на фазі пакета з метою копіювання, і він завантажить будь-який файл у сховище Maven (включаючи файли WAR) і запише їх там, де вам це потрібно. Я змінив вихідний каталог на $ {project.build.directory} / class, і тоді кінцевим результатом є те, що звичайне завдання JAR включає мої файли просто чудово. Потім я можу їх витягнути і записати в каталог встановлення.

<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

Дякую, що я додав нижче фрагмент у файл POM.xml і вирішено проблему Mp, і створити файл жирного банку, який включає всі залежні банки.

<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>
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.