Як я можу створити виконуваний JAR із залежностями за допомогою Maven?


2396

Я хочу упакувати свій проект у єдиний виконуваний JAR для розповсюдження.

Як я можу зробити пакет проекту Maven усі JAR-групи залежностей у свій вихідний JAR?


14
Поясніть, будь ласка, до якої мети плагіна залежності ви звертаєтесь. Я не знаю жодної мети, яка робить те, що вимагає оригінальне запитання: поставити всі залежності або A) всередині авторів банку за допомогою перепаковки, або B) зробити виконувану банку, яку мають інші в класній стежині MANIFEST.MF
Меттью МакКаллоу

2
Ви могли б знайти це корисним rationaljava.com/2015/02 / ...
Dan


Відповіді:


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

і ти запускаєш його

mvn clean compile assembly:single

Ціль компіляції слід додати перед складанням: одиничний або інший код у вашому власному проекті не включений.

Детальніше дивіться в коментарях.


Зазвичай ця мета пов'язана з фазою збирання, яка виконується автоматично. Це гарантує, що JAR будується під час виконання mvn installабо виконання розгортання / випуску.

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

22
Дякуємо @IAdapter. Зауважте, що ви завжди повинні робити компіляцію перед рукою, оскільки вона просто помістить все, що є в "цілі / класи" в JAR. Це забезпечить включення до JAR будь-яких змін, які ви нещодавно внесли у вихідний код. Таким чином, ви повинні зробити що - щось на кшталт: mvn clean compile assembly:single.
Майкл

10
Я відредагував питання, щоб включити фазове зв'язування. Я зняв застарілу ціль складання, тому що нікому про це не потрібно знати.
Дункан Джонс

2
Я бачу, що це не додає банки в банку uber, натомість це просто додає всі файли класу в банку.
pitchblack408

170
Порада: ви також можете додати елемент <appendAssemblyId>false</appendAssemblyId>у, configurationщоб уникнути набридливого суфікса "-jar-with-зависимост" у назві
maxivis

6
забудь, compileі ти накручений.
prayagupd

349

Ви можете використовувати плагін залежності, щоб генерувати всі залежності в окремому каталозі перед фазою пакету, а потім включити його в класний шлях маніфесту:

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

Крім того, використовуйте ${project.build.directory}/classes/libяк OutputDirectory, щоб інтегрувати всі jar-файли в основну банку, але тоді вам потрібно буде додати спеціальний код завантаження для завантаження банок.


3
+1 Відмінно Причина, по якій я переходжу з плагіном maven-залежність, а не плагін maven-Assembly-plugin, полягає в тому, що я також використовую buildnumber-maven-plugin, і таким чином я можу зберігати номер версії в маніфесті кожної банку окремо.
PapaFreud

17
Мені подобається ваше рішення. Я використовую ${project.build.directory}/classes/libяк outputDirectoryодин основний .jar з усіма залежностями всередині, але - Як додати спеціальний код для завантаження класу для завантаження цих банок? Мені потрібно , щоб зробити виконання робіт , як: java -jar main-jar-with-deps.jar. Чи можливо це?
marioosh

3
@ André Aronsen, я використав це рішення, щоб додати залежності в папці lib всередині банку, але я завжди отримує виняток, не знайдений класом, чи можете ви порадити, як це виправити.
Махмуд Салех

11
+1 вам !! Схоже, плагін Maven Assembly 'jar-with-залежностей' не дуже добре працює. Мені не вистачало деяких записів з META-INF / spring.schemas у створеній банці. Тож я вирізав залежно від залежностей і використав ваше рішення вище. Ідеальне спасибі !!!
Дерек

9
Для всіх, хто стикається з цією проблемою, ви повинні включити папку lib у той самий каталог із вашою банку, куди б ви не перевозили банку.
Шпалери

224

Я блогів про деякі різні способи зробити це.

Дивіться виконувану банку з Apache Maven (WordPress)

або виконуваний jar-with-maven-example (GitHub)

Примітки

Ці плюси і мінуси надає Стефан .


Для ручного розгортання

  • Плюси
  • Мінуси
    • Залежності виходять з остаточної банки.

Скопіюйте залежності в певний каталог

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

Зробіть обізнаність про виконувану та класний шлях

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

На цьому етапі jarфактично виконується із зовнішніми елементами classpath.

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

Зробіть розгортаються архіви

jarФайл є виконуваним тільки з родинним ...lib/каталогом. Нам потрібно зробити архіви для розгортання з каталогом та його вмістом.

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

Тепер у вас є target/${project.build.finalName}.(zip|tar|tar.bz2|tar.gz)кожен, який містить jarі lib/*.


Плагін для збірки Apache Maven

  • Плюси
  • Мінуси
    • Немає підтримки переїзду класу (використовуйте плагін Maven-shadow-плагін, якщо потрібен переїзд класу).
<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>

У вас є target/${project.bulid.finalName}-jar-with-dependencies.jar.


Apache Maven Shade Plugin

  • Плюси
  • Мінуси
<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>

У вас є target/${project.build.finalName}-shaded.jar.


onejar-maven-плагін

  • Плюси
  • Мінуси
    • Не підтримується активно з 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>

Плагін Spring Boot Maven

  • Плюси
  • Мінуси
    • Додайте потенційні непотрібні класи, пов’язані з весною та весняними завантаженнями.
<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>

У вас є target/${project.bulid.finalName}-spring-boot.jar.


2
@caiohamamura Ви можете клонувати репозиторій GitHub і подивитися, як працюють усі профілі.
Джин Квон

Проблема була з пакетом , який я використовував: stackoverflow.com/a/12622037/2548351
caiohamamura

1
Я думаю, що це, мабуть, найповніша відповідь на цю тему.
Петро Боднар

139

Отримавши відповідь без відповіді та переформатувавши її, ми маємо:

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

Далі я рекомендую зробити це природною частиною вашої збірки, а не щось чітко зателефонувати. Щоб зробити це невід’ємною частиною вашої збірки, додайте цей плагін до свого pom.xmlі прив’яжіть його до packageподії життєвого циклу. Однак, gotcha полягає в тому, що вам потрібно зателефонувати до assembly:singleцілі, якщо помістити це у свій pom.xml, тоді як ви будете викликати "Assembly: Assembly", якщо виконувати його вручну з командного рядка.

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

10
Використання підходу в цій відповіді призводить до наступного повідомлення про помилку: 'Не вдалося завантажити атрибут маніфесту Main-Class з <jar file>', коли намагалися запустити JAR за допомогою 'java -jar <jar file>'
Elmo,

3
Архівна частина додатка Maven-jar потрібна <archive> <manifest> <addClasspath> true </addClasspath> <mainClass> full.qualified.MainClass </mainClass> </manifest> </archive>
Rade_303

4
Вибачте, ця відповідь явно невірна, тег mainClass повинен міститись у програмі Maven-Assembly-плагін, оскільки ви це називаєте під час мети пакету
Alex Lehmann

Я здивований, чому пом.xml вже не може включати це після архетипу mvn: create command? Це щось дратує ручне копіювання та вставлення цього тексту кожного разу, коли я створюю новий проект Maven ...
wintermute

у мене немає головного методу чи класу, у мене просто клас з функцією. як я можу зробити баночку та використав її
парлад

97

Використовуйте плагін maven-shadow - щоб упакувати всі залежності в одну uber-jar. Він також може бути використаний для створення виконуваної банки, вказавши основний клас. Спробувавши використовувати maven-Assembly та maven-jar, я виявив, що цей плагін найкраще відповідає моїм потребам.

Я вважаю цей плагін особливо корисним, оскільки він об'єднує вміст певних файлів, а не перезаписує їх. Це потрібно, коли в банках є файли ресурсів, які мають однакове ім'я, і ​​плагін намагається упакувати всі файли ресурсів

Дивіться приклад нижче

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

Тож як bcprov-jdk15.jar потрапляє на класний шлях під час виконання, враховуючи, що це виключено з процесу затінення?
Ендрю Лебедь

Це натягнуло на себе cxf-rt-ws-security, який є частиною моїх залежностей
Vijay Katam

Ніколи не чув про цей плагін раніше, але це вирішило мою проблему з spring.handlers всередині банки. Дякую!
Олександр L Теллес

11
Ті, хто отримав виняток із безпеки, виключають DSA із Маніфесту. Перевірте maven.apache.org/plugins/maven-shade-plugin/examples/…
ruhsuzbaykus

+1 Я раніше використовував minijar: ueberjar, але плагін minijar зараз застарілий і замінений на тінь
rds

19

Довго користувався плагіном збірки Maven , але я не зміг знайти рішення проблеми "already added, skipping". Тепер я використовую ще один плагін - onejar-maven-plugin . Приклад нижче ( mvn packageзбірка банку):

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

Вам потрібно додати сховище для цього плагіна:

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

як позбутися зайвих повідомлень на виході?
Олександр

17

Ви можете використовувати плагін maven-зависимості, але питання полягало у тому, як створити виконуваний JAR. Для цього потрібна наступна зміна відповіді Меттью Франглена (btw, використовуючи плагін залежності, потрібно тривати більше часу, коли починається з чистої цілі):

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

16

Ви можете використовувати плагін Maven-shadow для створення баночки uber, як показано нижче

<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-shade-plugin</artifactId>
    <executions>
        <execution>
            <phase>package</phase>
            <goals>
                <goal>shade</goal>
            </goals>
        </execution>
    </executions>
</plugin>

Але тоді як це буде розгорнуто для репо?
Франческо Гуалацці

15

Інший варіант, якщо ви дійсно хочете перепакувати інший вміст JAR всередині вашого єдиного результату JAR, це плагін Maven Assembly . Він розпаковується, а потім перепаковує все в каталог через <unpack>true</unpack>. Тоді у вас буде другий прохід, який вбудував його в один масивний JAR.

Інший варіант - плагін OneJar . Це виконує вищезазначені дії з упаковки все в один крок.


14

Ви можете додати до свого pom.xml :

<build>
<defaultGoal>install</defaultGoal>
<plugins>
  <plugin>
    <artifactId>maven-compiler-plugin</artifactId>
    <version>2.3.2</version>
    <configuration>
      <source>1.6</source>
      <target>1.6</target>
    </configuration>
  </plugin>
  <plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-jar-plugin</artifactId>
    <version>2.3.1</version>
    <configuration>
      <archive>
        <manifest>
          <addClasspath>true</addClasspath>
          <mainClass>com.mycompany.package.MainClass</mainClass>
        </manifest>
      </archive>
    </configuration>
  </plugin>
  <plugin>
    <artifactId>maven-assembly-plugin</artifactId>
    <configuration>
      <descriptorRefs>
        <descriptorRef>jar-with-dependencies</descriptorRef>
      </descriptorRefs>
      <archive>
        <manifest>
          <mainClass>com.mycompany.package.MainClass</mainClass>
        </manifest>
      </archive>
    </configuration>
    <executions>
      <execution>
        <id>make-my-jar-with-dependencies</id>
        <phase>package</phase>
        <goals>
          <goal>single</goal>
        </goals>
      </execution>
    </executions>
  </plugin>
</plugins>
</build>

Після цього потрібно переключитися через консоль до каталогу, де знаходиться pom.xml. Тоді вам доведеться виконати збірку mvn: поодинокий, і тоді ваш виконуваний файл JAR із залежностями буде, сподіваємось, побудований. Ви можете перевірити це при переключенні на каталог вихідних (цільових) за допомогою cd ./target та запуску jar із командою, подібною до java -jar mavenproject1-1.0-SNAPSHOT-jar-with-зависимоtions.jar .

Я перевірив це за допомогою Apache Maven 3.0.3 .


13

Я переглянув кожну з цих відповідей, прагнучи зробити жирну виконувану банку, що містить усі залежності, і жодна з них не працювала правильно. Відповідь - плагін відтінку, його дуже легкий і простий.

    <plugin>
      <groupId>org.apache.maven.plugins</groupId>
      <artifactId>maven-shade-plugin</artifactId>
      <version>2.3</version>
      <executions>
         <!-- Run shade goal on package phase -->
        <execution>
        <phase>package</phase>
        <goals>
            <goal>shade</goal>
        </goals>
        <configuration>
          <transformers>
             <transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
                <mainClass>path.to.MainClass</mainClass>
             </transformer>
          </transformers>
        </configuration>
          </execution>
      </executions>
    </plugin>

Будьте в курсі, що для вашої належної роботи потрібно мати обсяг компіляції або час виконання.

Цей приклад прийшов з сайту mkyong.com


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

2
pluginЕлемент потрапляє в pom.xmlUnder build/plugins.
isapir

12

Ви можете поєднати maven-shade-pluginі maven-jar-plugin.

  • maven-shade-pluginПакети класів і всю залежність в одному файлі фляга.
  • Налаштуйте параметр, maven-jar-pluginщоб вказати основний клас виконуваної вами банку (див. Налаштування Classpath , розділ "Зробіть Jar виконуваним").

Приклад конфігурації POM для maven-jar-plugin:

        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-jar-plugin</artifactId>
            <version>2.3.2</version>
            <configuration>
                <archive>
                    <manifest>
                        <addClasspath>true</addClasspath>
                        <mainClass>com.example.MyMainClass</mainClass>
                    </manifest>
                </archive>
            </configuration>
        </plugin>

Нарешті створіть виконувану банку за допомогою виклику:

mvn clean package shade:shade

3
Тепер плагін Shade має змогу вказати
Чадвік

9

На мою думку, Кен Лю це правильно. Плагін залежності maven дозволяє розширити всі залежності, які ви можете потім розглядати як ресурси. Це дозволяє включити їх до основного артефакту. Використання модуля збірки створює вторинний артефакт, який важко змінити - у моєму випадку я хотів додати власні записи маніфесту. Моя пом’янка закінчилася так:

<project>
 ...
 <build>
  <plugins>
   <plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <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>
    <targetPath>/</targetPath>
   </resource>
  </resources>
 </build>
 ...
</project>

1
Дійсно приємно! Чи не було б краще використовувати фазу генерування ресурсів для розпакування?
nawroth

9

Він повинен бути таким:

<plugin>
    <artifactId>maven-dependency-plugin</artifactId>
    <executions>
        <execution>
            <id>unpack-dependencies</id>
            <phase>generate-resources</phase>
            <goals>
                <goal>unpack-dependencies</goal>
            </goals>
        </execution>
    </executions>
</plugin>

Розпакування повинно бути у фазі генерування ресурсів, оскільки, якщо вона знаходиться у фазі пакета, вона не буде включена як ресурси. Спробуйте чистий пакет і побачите.


7

Проблема з розміщенням файлу спільної збірки з maven-Assembly-plugin-2.2.1?

Спробуйте використовувати параметр конфігурації deskriptor замість дескрипторів / дескриптора або дескриптораRefs / дескриптораRef параметрів.

Жоден із них не робить те, що потрібно: шукайте файл на classpath. Звичайно, вам потрібно додати пакет, де спільна збірка знаходиться на класному шляху maven-Assembly-плагіна (див. Нижче). Якщо ви використовуєте Maven 2.x (не Maven 3.x), можливо, вам знадобиться додати цю залежність у найпопулярніший батьківський pom.xml у розділі pluginManagement.

Дивіться це для більш детальної інформації.

Клас: org.apache.maven.plugin.assembly.io.DefaultAssemblyReader

Приклад:

        <!-- Use the assembly plugin to create a zip file of all our dependencies. -->
        <plugin>
            <artifactId>maven-assembly-plugin</artifactId>
            <version>2.2.1</version>
            <executions>
                <execution>
                    <id>make-assembly</id>
                    <phase>package</phase>
                    <goals>
                        <goal>single</goal>
                    </goals>
                    <configuration>
                        <descriptorId>assembly-zip-for-wid</descriptorId>
                    </configuration>
                </execution>
            </executions>
            <dependencies>
                <dependency>
                    <groupId>cz.ness.ct.ip.assemblies</groupId>
                    <artifactId>TEST_SharedAssemblyDescriptor</artifactId>
                    <version>1.0.0-SNAPSHOT</version>
                </dependency>
            </dependencies>
        </plugin>

7

Щоб вирішити цю проблему, ми будемо використовувати плагін Maven Assembly, який створить JAR разом із JAR-адресами своєї залежності в єдиний виконуваний файл JAR. Просто додайте нижче конфігурацію плагінів у файл pom.xml.

<build>
   <pluginManagement>
      <plugins>
         <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-assembly-plugin</artifactId>
            <configuration>
               <archive>
                  <manifest>
                     <addClasspath>true</addClasspath>
                     <mainClass>com.your.package.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>
   </pluginManagement>
</build>

Після цього не забудьте запустити інструмент MAVEN з цією командою mvn clean compile Assembly: single

http://jkoder.com/maven-creating-a-jar-together-with-its-dependency-jars-into-a-single-executable-jar-file/


5

Я не відповім прямо на це питання, оскільки інші вже робили це раніше, але мені дуже цікаво, чи гарна ідея вставити всі залежності в саму банку проекту.

Я бачу сенс (простота розгортання / використання), але це залежить від випадку використання вашого об'єкта (і можуть бути альтернативи (див. Нижче)).

Якщо ви використовуєте його повністю самостійно, чому б ні.

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

Хороша альтернатива:

  • розгорніть свою програму як .zip / .war: архів містить банку вашого проекту та всі залежні банки;
  • використовуйте динамічний механізм завантажувача класів (див. Весна, або ви можете легко зробити це самостійно), щоб мати єдину точку входу вашого проекту (один клас для початку - див. механізм Manifest в іншій відповіді), який додасть (динамічно) до поточний класний шлях усіх інших необхідних банок.

Ось так, маючи в кінцевому підсумку лише маніфест і "спеціальний динамічний основний завантажувач основних", ви можете розпочати свій проект із:

java -jar ProjectMainJar.jar com.stackoverflow.projectName.MainDynamicClassLoaderClass

1
Як тоді помістити банку з проектом та всі залежні банки в архів?

4

Щоб створити виконуваний JAR з самого командного рядка, просто запустіть команду нижче з шляху проекту:

mvn assembly:assembly

3
Я думаю, вам все-таки потрібно зробити деякі речі в pom.xmlіншому випадку Error reading assemblies: No assembly descriptors found.. Ось що у мене все одно відбувається.
Шрідхар Сарнобат

3

Це найкращий спосіб, який я знайшов:

  <plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-jar-plugin</artifactId>
    <version>2.4</version>
    <configuration>
      <archive>
        <manifest>
        <addClasspath>true</addClasspath>
        <mainClass>com.myDomain.etc.MainClassName</mainClass>
        <classpathPrefix>dependency-jars/</classpathPrefix>
        </manifest>
      </archive>
    </configuration>
  </plugin>
  <plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-dependency-plugin</artifactId>
    <version>2.5.1</version>
    <executions>
      <execution>
        <id>copy-dependencies</id>
        <phase>package</phase>
        <goals>
            <goal>copy-dependencies</goal>
        </goals>
        <configuration>
            <outputDirectory>
               ${project.build.directory}/dependency-jars/
            </outputDirectory>
        </configuration>
      </execution>
    </executions>
  </plugin>

При такій конфігурації всі залежності будуть розташовані в /dependency-jars. У моєї програми немає Mainкласу, а лише контекстні, але одна з моїх залежностей має Mainклас ( com.myDomain.etc.MainClassName), який запускає сервер JMX і отримує параметр startабо stop. Тож із цим я зміг запустити заявку так:

java -jar ./lib/TestApp-1.0-SNAPSHOT.jar start

Я чекаю, що буде корисним для всіх вас.


3

Я порівняв плагіни дерев, згадані в цій публікації. Я створив 2 банки та каталог із усіма банками. Я порівняв результати і, безумовно, плагін Maven-shadow є найкращим. Моя проблема полягала в тому, що у мене є кілька джерельних джерел, які потрібно об'єднати, а також jax-rs та JDBC послуги. Всі вони були об'єднані належним чином плагіном для відтінку порівняно з плагіном maven-Assembly-плагіном. У такому випадку пружина не вдасться, якщо ви не скопіюєте їх у папку власних ресурсів і не з’єднаєте їх одночасно вручну. Обидва плагіни виводять правильне дерево залежності. У мене було кілька областей, як тестування, надання, компіляція тощо, і тест був наданий обома плагінами. Вони обидва видали однаковий маніфест, але мені вдалося консолідувати ліцензії за допомогою плагін відтінку, використовуючи їх трансформатор. З плагіном залежності від Maven, звичайно, ви не хочете ' не матимуть цих проблем, оскільки банки не витягуються. Але, як і деякі інші вказали, вам потрібно мати один додатковий файл (и), щоб правильно працювати. Ось фрагмент pom.xml

            <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>
                        <includeScope>compile</includeScope>
                        <excludeTransitive>true</excludeTransitive>
                        <overWriteReleases>false</overWriteReleases>
                        <overWriteSnapshots>false</overWriteSnapshots>
                        <overWriteIfNewer>true</overWriteIfNewer>
                    </configuration>
                </execution>
            </executions>
        </plugin>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-assembly-plugin</artifactId>
            <version>2.6</version>
            <configuration>
                <archive>
                    <manifest>
                        <addClasspath>true</addClasspath>
                        <mainClass>com.rbccm.itf.cdd.poller.landingzone.LandingZonePoller</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>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-shade-plugin</artifactId>
            <version>2.4.3</version>
            <configuration>
                <shadedArtifactAttached>false</shadedArtifactAttached>
                <keepDependenciesWithProvidedScope>false</keepDependenciesWithProvidedScope>
                <transformers>
                    <transformer implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
                        <resource>META-INF/services/javax.ws.rs.ext.Providers</resource>
                    </transformer>
                    <transformer implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
                        <resource>META-INF/spring.factories</resource>
                    </transformer>
                    <transformer implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
                        <resource>META-INF/spring.handlers</resource>
                    </transformer>
                    <transformer implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
                        <resource>META-INF/spring.schemas</resource>
                    </transformer>
                    <transformer implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
                        <resource>META-INF/spring.tooling</resource>
                    </transformer>
                    <transformer implementation="org.apache.maven.plugins.shade.resource.ServicesResourceTransformer"/>
                    <transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer"/>
                    <transformer implementation="org.apache.maven.plugins.shade.resource.ApacheLicenseResourceTransformer">
                    </transformer>
                </transformers>
            </configuration>
            <executions>
                <execution>
                    <goals>
                        <goal>shade</goal>
                    </goals>
                </execution>
            </executions>
        </plugin>

2

Щось для мене спрацювало:

  <plugin>
    <artifactId>maven-dependency-plugin</artifactId>
    <executions>
      <execution>
        <id>unpack-dependencies</id>
        <phase>prepare-package</phase>
        <goals>
          <goal>unpack-dependencies</goal>
        </goals>
        <configuration>
          <outputDirectory>${project.build.directory}/classes</outputDirectory>
        </configuration>
      </execution>

    </executions>
  </plugin>


  <plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-jar-plugin</artifactId>
    <executions>
      <execution>
        <id>unpack-dependencies</id>
        <phase>package</phase>
      </execution>
    </executions>
    <configuration>
      <archive>
        <manifest>
          <addClasspath>true</addClasspath>
          <classpathPrefix>lib/</classpathPrefix>
          <mainClass>SimpleKeyLogger</mainClass>
        </manifest>
      </archive>
    </configuration>
  </plugin>

У мене був надзвичайний випадок, тому що моя залежність була першою системою:

<dependency>
  ..
  <scope>system</scope>
  <systemPath>${project.basedir}/lib/myjar.jar</systemPath>
</dependency>

Я змінив код, наданий @ user189057, із змінами: 1) плагін maven-залежність виконується у фазі "підготовка-пакет" 2) я витягую розпакований класс безпосередньо на "target / class"


2

Тут я спробував відповісти, що найбільше голосував, і зміг отримати баночку, яку можна виконати. Але програма не працювала коректно. Я не знаю, в чому причина. Коли я намагаюся бігти відEclipse , я отримую інший результат, але коли я запускаю jar з командного рядка, я отримую інший результат (він виходить з ладу під час виконання програмної помилки).

У мене була така ж вимога, що і в ОП, тільки те, що я мав занадто багато (Maven) залежностей для свого проекту. На щастя, єдине рішення, яке працювало для мене, - це використання Eclipse. Дуже просто і дуже прямо. Це не є рішенням щодо ОП, але це рішення для тих, хто має подібну вимогу, але з багатьма залежностями Мейвена,

1) Просто натисніть правою кнопкою миші папку вашого проекту (у Eclipse) та виберіть Export

2) Потім виберіть Java->Runnable Jar

3) Вам буде запропоновано вибрати розташування файлу jar

4) Нарешті, виберіть клас із основним методом, який потрібно запустити, та оберіть Package dependencies with the Jar fileта клацнітьFinish


2

Це також може бути варіантом. Ви зможете створити свій jar файл

<build>
    <plugins>
        <plugin>
            <!-- Build an executable JAR -->
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-jar-plugin</artifactId>
            <version>2.4</version>
            <configuration>
                <archive>
                    <manifest>
                        <addClasspath>true</addClasspath>
                        <classpathPrefix>lib/</classpathPrefix>
                        <mainClass>WordListDriver</mainClass>
                    </manifest>
                </archive>
            </configuration>
        </plugin>
    </plugins>
</build>

2

Для тих, хто шукає варіанти виключити конкретні залежності з uber-jar, це рішення, яке працювало для мене:

<project...>
<dependencies>
        <dependency>
            <groupId>org.apache.spark</groupId>
            <artifactId>spark-core_2.11</artifactId>
            <version>1.6.1</version>
            <scope>provided</scope> <=============
        </dependency>
</dependencies>
<build>
        <plugins>
            <plugin>
                <artifactId>maven-assembly-plugin</artifactId>
                <configuration>
                    <descriptorRefs>
                        <descriptorRef>jar-with-dependencies</descriptorRef>
                    </descriptorRefs>
                    <archive>
                        <manifest>
                            <mainClass>...</mainClass>
                        </manifest>
                    </archive>
                </configuration>
                <executions>
                    <execution>
                        <id>make-assembly</id>
                        <phase>package</phase>
                        <goals>
                            <goal>single</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>
</project>

Отже, це не конфігурація mvn-Assembly-плагіна, а властивість залежності.


2

Є вже мільйони відповідей, я хотів додати, що вам не потрібно, <mainClass>якщо вам не потрібно додавати entryPoint у свою програму. Наприклад, API може не обов’язково мати mainметод.

Maven плагін config

  <build>
    <finalName>log-enrichment</finalName>
    <plugins>
      <plugin>
        <artifactId>maven-assembly-plugin</artifactId>
        <configuration>
          <descriptorRefs>
            <descriptorRef>jar-with-dependencies</descriptorRef>
          </descriptorRefs>
        </configuration>
      </plugin>
    </plugins>
  </build>

будувати

mvn clean compile assembly:single

перевірити

ll target/
total 35100
drwxrwx--- 1 root vboxsf     4096 Sep 29 16:25 ./
drwxrwx--- 1 root vboxsf     4096 Sep 29 16:25 ../
drwxrwx--- 1 root vboxsf        0 Sep 29 16:08 archive-tmp/
drwxrwx--- 1 root vboxsf        0 Sep 29 16:25 classes/
drwxrwx--- 1 root vboxsf        0 Sep 29 16:25 generated-sources/
drwxrwx--- 1 root vboxsf        0 Sep 29 16:25 generated-test-sources/
-rwxrwx--- 1 root vboxsf 35929841 Sep 29 16:10 log-enrichment-jar-with-dependencies.jar*
drwxrwx--- 1 root vboxsf        0 Sep 29 16:08 maven-status/

2

Додати в pom.xml:

  <dependency>
            <groupId>com.jolira</groupId>
            <artifactId>onejar-maven-plugin</artifactId>
            <version>1.4.4</version>
  </dependency>

і

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

Це воно. Наступний пакет mvn також створить ще одну банку жиру додатково, включаючи всі банки для залежності.


1

Плагін maven-Assembly-відмінно працював для мене. Я проводив години з плагіном залежності від Maven і не міг змусити його працювати. Основна причина полягала в тому, що мені довелося чітко визначити в розділі конфігурації елементи артефакту, які слід включити так, як це описано в документації . Є приклад для тих випадків, коли ви хочете використовувати його на зразок:, mvn dependency:copyде немає включених артефактів, але це не працює.


1

У цій публікації в блозі показаний інший підхід із поєднанням плагінів Maven-jar та Maven-Assembly. За допомогою конфігурації збірки xml з повідомлення в блозі також можна керувати, якщо залежність буде розширена або просто буде зібрана в папку і на яку посилається запис в класі маніфесту:

Ідеальним рішенням є включення банок у папку lib, а у файл маніфесту.mf основної банки містяться всі банки на classpath.

І саме це описано тут: https://caffebig.wordpress.com/2013/04/05/executable-jar-file-with-dependent-jars-using-maven/


0
<build>
    <plugins>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-assembly-plugin</artifactId>
            <version>2.4.1</version>
            <configuration>
                <!-- get all project dependencies -->
                <descriptorRefs>
                    <descriptorRef>jar-with-dependencies</descriptorRef>
                </descriptorRefs>
            </configuration>
            <executions>
                <execution>
                    <id>make-assembly</id>
                    <!-- bind to the packaging phase -->
                    <phase>package</phase>
                    <goals>
                        <goal>single</goal>
                    </goals>
                </execution>
            </executions>
        </plugin>
    </plugins>
</build>

1
Потрібно трохи більше пояснення цьому; це коментарі - лише документація, чи потрібні додаткові параметри для розміщення цих коментарів?
Марк Стюарт

-2

Гаразд, тож це моє рішення. Я знаю, що не використовується файл pom.xml. Але у мене виникла проблема з компіляцією та запуском програми в Netbeans, але вона не вдалася, коли я спробував Java -jar MyJarFile.jar. Тепер я не повністю розумію Maven, і я думаю, що саме тому виникли проблеми з отриманням Netbeans 8.0.2, щоб включити мій файл jar в бібліотеку, щоб помістити їх у файл jar. Я думав про те, як я використовував файли jar без Maven in Eclipse.

Саме Maven може зібрати всі залежності і плагіни. Не Netbeans. (Якщо ви можете отримати Netbeans і зможете використовувати java .jar для цього, будь ласка, скажіть мені, як (^. ^) V)

[Вирішено - для Linux], відкривши термінал.

Тоді

cd /MyRootDirectoryForMyProject

Далі

mvn org.apache.maven.plugins:maven-compiler-plugin:compile

Далі

mvn install

Це створить файл jar в цільовому каталозі.

MyJarFile-1.0-jar-with-dependencies.jar

Тепер

cd target

(Можливо, вам доведеться запустити: chmod +x MyJarFile-1.0-jar-with-dependencies.jar )

І, нарешті

java -jar MyJarFile-1.0-jar-with-dependencies.jar

Будь ласка, дивіться

https://cwiki.apache.org/confluence/display/MAVEN/LifecyclePhaseNotFoundException

Я опублікую це рішення на кількох інших сторінках із подібною проблемою. Сподіваюся, я можу врятувати когось від тижня розчарування.


2
Спробуйте відкрити проект Maven, який ви створили з Netbeans. Основне правило Netbeans - це завжди створити проект Maven і ніколи не "Java-додаток". Додайте плагін maven-shadow, як один із відповідей. Працює як шарм.
rjdkolb
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.