Как я могу создать исполняемый JAR с зависимостями, используя Maven? - PullRequest
2171 голосов
/ 22 февраля 2009

Я хочу упаковать свой проект в один исполняемый файл JAR для распространения.

Как сделать так, чтобы проект Maven упаковывал все JAR-файлы зависимостей в мой выходной JAR-файл?

Ответы [ 34 ]

2 голосов
/ 10 марта 2015

Это лучший способ, который я нашел:

  <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

Я жду, что это будет полезно для всех вас.

2 голосов
/ 11 октября 2014

Я попытался получить наиболее одобренный ответ и смог запустить флягу. Но программа не работает правильно. Я не знаю, в чем причина. Когда я пытаюсь запустить из Eclipse, я получаю другой результат, но когда я запускаю jar из командной строки, я получаю другой результат (он вылетает из-за ошибки времени выполнения программы).

У меня было такое же требование, как и у ОП, только у меня было слишком много зависимостей (Maven) для моего проекта. К счастью, единственное решение, которое мне помогло, это использование Eclipse. Очень просто и очень просто. Это не решение OP, но решение для кого-то, у кого есть подобное требование, но с множеством зависимостей Maven,

1) Просто щелкните правой кнопкой мыши папку вашего проекта (в Eclipse) и выберите Export

2) Затем выберите Java -> Runnable Jar

3) Вам будет предложено выбрать местоположение файла jar

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

2 голосов
/ 24 сентября 2013

Что-то, что сработало для меня, было:

  <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-dependency-plugin выполняется в фазе "prepare-package" 2) Я распаковываю распакованный класс прямо в "target / classes"

2 голосов
/ 29 января 2014

Вы также можете использовать этот плагин, он довольно хорош, и я использую его для упаковки своих банок http://sonatype.github.io/jarjar-maven-plugin/

2 голосов
/ 21 июня 2017

Добавить в 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 также создаст еще один толстый jar-файл, включая все jar-файлы зависимостей.

2 голосов
/ 30 сентября 2016

Уже есть миллионы ответов, я хочу добавить, что вам не нужно <mainClass>, если вам не нужно добавлять entryPoint в ваше приложение. Например, API могут не обязательно иметь метод main.

Конфигурация плагина maven

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

1010 * сборка * 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 голосов
/ 03 мая 2016

Для тех, кто ищет варианты исключения определенных зависимостей из 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-plugin, а свойство зависимости.

2 голосов
/ 24 февраля 2016

Я сравнил дерево плагинов, упомянутых в этом посте. Я сгенерировал 2 банки и каталог со всеми банками. Я сравнил результаты и определенно лучше всего подходит maven-shade-plugin. Моя проблема заключалась в том, что у меня есть несколько ресурсов Spring, которые необходимо объединить, а также Jax-rs и JDBC-сервисы. Все они были слиты корректно плагином shade по сравнению с плагином maven-assembly-plugin. В этом случае пружина потерпит неудачу, если вы не скопируете их в свою папку ресурсов и не объедините их вручную один раз. Оба плагина выводят правильное дерево зависимостей. У меня было несколько областей, таких как test, предоставить, скомпилировать и т.д. Они оба создали один и тот же манифест, но я смог объединить лицензии с плагином Shade, используя их преобразователь. Конечно, с плагином maven-dependency-plugin у вас нет таких проблем, потому что файлы jar не извлекаются. Но, как некоторые другие указали, вам нужно иметь один дополнительный файл (ы) для правильной работы. Вот фрагмент 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>
1 голос
/ 24 мая 2013

Плагин maven-assembly-plugin отлично работал для меня. Я провел часы с плагином maven-dependency-и не мог заставить его работать. Основной причиной было то, что мне пришлось явно указать в разделе конфигурации элементы артефакта, которые должны быть включены, как описано в документации . Там есть пример для случаев, когда вы хотите использовать его, например: mvn dependency:copy, где нет включенных артефактов, но он не работает.

1 голос
/ 25 ноября 2015

Это также может быть вариантом, вы сможете создать свой файл 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>
...