Как я могу создать исполняемый JAR с зависимостями, используя Maven?
Я хочу упаковать свой проект в один исполняемый файл JAR для распространения.
Как сделать пакет проекта Maven всеми JAR-файлами зависимостей в свой выходной JAR-файл?
37 ответов
<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>
Вы можете использовать плагин зависимостей для генерации всех зависимостей в отдельном каталоге до фазы пакета и затем включить их в путь к классам манифеста:
<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-файлы в основной jar, но тогда вам нужно будет добавить пользовательский код загрузки классов для загрузки jar.
Я написал в блоге о некоторых различных способах сделать это.
Смотрите исполняемый файл Jar с Apache Maven (WordPress)
или исполняемый jar-with-maven-пример (GitHub)
Заметки
Эти плюсы и минусы предоставлены Stephan.
Для ручного развертывания
- Pros
- Cons
- Зависимости выходят из финальной фляги.
Копировать зависимости в конкретный каталог
<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>
Сделать Jar исполняемым и Classpath Aware
<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
- Pros
- Cons
- Нет поддержки перемещения классов (используйте maven-shade-plugin, если необходимо перемещение классов).
<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
- Pros
- Cons
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<executions>
<execution>
<goals>
<goal>shade</goal>
</goals>
<configuration>
<shadedArtifactAttached>true</shadedArtifactAttached>
<transformers>
<transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
<mainClass>${fully.qualified.main.class}</mainClass>
</transformer>
</transformers>
</configuration>
</execution>
</executions>
</plugin>
У тебя есть target/${project.build.finalName}-shaded.jar
,
onejar-Maven-плагин
- Pros
- Cons
- Не активно поддерживается с 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 Плагин
- Pros
- Cons
- Добавьте потенциально ненужные классы, связанные с Spring и Spring Boot.
<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
,
Принимая ответ без ответа и переформатируя его, мы имеем:
<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
событие жизненного цикла. Тем не менее, уловка в том, что вам нужно позвонить assembly:single
цель, если вы поместите это в ваш pom.xml, в то время как вы вызовете "сборка: сборка", если выполните его вручную из командной строки.
<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>
Используйте maven-shade-plugin, чтобы упаковать все зависимости в один uber-jar. Его также можно использовать для создания исполняемого файла 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>
Вы можете использовать плагин Maven-Shade для создания Uber Jar, как показано ниже
<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>
Долго пользовался плагином сборки 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>
Вы можете добавить следующее в ваш 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:single, и, надеюсь, ваш исполняемый JAR-файл с зависимостями будет собран. Вы можете проверить это, переключившись в выходной (целевой) каталог с помощью cd ./target и запустив свой jar с помощью команды, подобной java -jar mavenproject1-1.0-SNAPSHOT-jar-with-dependencies.jar.
Я протестировал это с Apache Maven 3.0.3.
Вы можете использовать maven-dependency-plugin, но вопрос был в том, как создать исполняемый JAR. Для этого требуется следующее изменение ответа Мэтью Френглена (кстати, использование плагина зависимости занимает больше времени при запуске с чистой цели):
<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>
Я просмотрел все эти ответы, пытаясь создать полный исполняемый файл jar, содержащий все зависимости, и ни один из них не работал правильно. Ответ - плагин Shade, он очень прост и понятен.
<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>
Имейте в виду, что ваши зависимости должны иметь область компиляции или времени выполнения для правильной работы.
Другой вариант, если вы действительно хотите упаковать другое содержимое JAR-файла внутри вашего единственного результирующего JAR-файла, - это плагин Maven Assembly. Распаковывает, а затем перепаковывает все в каталог через <unpack>true</unpack>
, Тогда у вас будет второй проход, который встроит его в один массивный JAR.
Другой вариант - плагин OneJar. Это выполняет вышеуказанные действия по переупаковке всего за один шаг.
Вы могли бы объединить maven-shade-plugin
а также maven-jar-plugin
,
maven-shade-plugin
упаковывает ваши классы и все зависимости в один файл jar.- Настройте
maven-jar-plugin
указать основной класс вашего исполняемого файла jar (см. " Настройка пути к классам", глава "Создание исполняемого файла 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>
Наконец, создайте исполняемый файл jar, вызвав:
mvn clean package shade:shade
Должно быть так:
<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>
Распаковка должна быть в фазе создания ресурсов, потому что, если она находится в фазе упаковки, она не будет включена в качестве ресурсов. Попробуйте чистую упаковку, и вы увидите.
Кен Лю имеет это право по моему мнению. Плагин зависимостей 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>
Чтобы решить эту проблему, мы будем использовать Maven Assembly Plugin, который создаст 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
Проблема с поиском общего файла сборки с помощью maven-assembly-plugin-2.2.1?
Попробуйте использовать параметр конфигурации descriptorId вместо параметров descriptors/descriptor или descriptorRefs/descriptorRef.
Ни один из них не делает то, что вам нужно: ищите файл в classpath. Конечно, вам нужно добавить пакет, где общая сборка находится в пути к классу maven-assembly-plugin (см. Ниже). Если вы используете 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>
Вот исполняемый плагин jar для Maven, который мы используем в Credit Karma. Создает банку банок с загрузчиком классов, способную загружать классы из вложенных банок. Это позволяет вам иметь один и тот же classpath в dev и prod и при этом хранить все классы в одном подписанном jar-файле.
https://github.com/creditkarma/maven-exec-jar-plugin
А вот сообщение в блоге с подробной информацией о плагине и почему мы его сделали: https://engineering.creditkarma.com/general-engineering/new-executable-jar-plugin-available-apache-maven/
Для тех, кто ищет варианты исключения определенных зависимостей из 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 банки и каталог со всеми банками. Я сравнил результаты и определенно лучше всего подходит 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>
Уже есть миллионы ответов, я хотел бы добавить, что вам не нужно <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>
строить
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/
Используйте плагин onejar, чтобы собрать его как один исполняемый файл jar, в который упакованы все файлы jar зависимостей. Это решило мою проблему, которая была похожа на это. Когда использовался плагин сборки, он распаковывал все jar-файлы зависимостей в исходную папку и перепаковывал их как jar-файл, переписывал все подобные реализации, которые были в моем коде, которые имели одинаковые имена классов. OneJar это простое решение здесь.
Что-то, что сработало для меня, было:
<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"
Это лучший способ, который я нашел:
<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
Я жду, что это будет полезно для всех вас.
Надеюсь, мой опыт может кому-то помочь: я хочу перенести свое приложение Spring (с помощью клиента cas) на Spring Boot (1.5, а не 2.4). Я столкнулся со многими проблемами, например:
нет основного атрибута манифеста в target / cas-client-web.jar
Я хочу сделать одну уникальную банку со всеми зависимостями. После нескольких дней поисков в Интернете. Я могу выполнить свою работу с помощью этих строк:
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<fork>true</fork>
<mainClass>${start-class}</mainClass>
</configuration>
<executions>
<execution>
<goals>
<goal>repackage</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
</execution>
</executions>
<configuration>
<archive>
<manifest>
<addClasspath>true</addClasspath>
<mainClass>${start-class}</mainClass>
</manifest>
</archive>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
</configuration>
</plugin>
with start-class - ваш основной класс
<properties>
<java.version>1.8</java.version>
<start-class>com.test.Application</start-class>
</properties>
И мое приложение похоже:
package com.test;
import java.util.Arrays;
import com.test.TestProperties;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean;
@SpringBootApplication
@EnableAutoConfiguration
@EnableConfigurationProperties({TestProperties.class})
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
@Bean
public CommandLineRunner commandLineRunner(ApplicationContext ctx) {
return args -> {
System.out.println("Let's inspect the beans provided by Spring Boot:");
String[] beanNames = ctx.getBeanDefinitionNames();
Arrays.sort(beanNames);
for (String beanName : beanNames) {
System.out.println(beanName);
}
};
}
}
Я не буду отвечать прямо на вопрос, так как другие уже делали это раньше, но мне действительно интересно, стоит ли встраивать все зависимости в сам файл проекта.
Я вижу смысл (простота развертывания / использования), но это зависит от варианта использования вашего проекта (и могут быть альтернативы (см. Ниже)).
Если вы используете его полностью автономно, почему бы и нет.
Но если вы используете свой проект в других контекстах (например, в веб-приложении или помещены в папку, где находятся другие jar-файлы), у вас могут быть дубликаты jar в вашем classpath (те, что в папке, те, что в банках). Может быть, не сделка, но я обычно избегаю этого.
Хорошая альтернатива:
- разверните свое приложение как.zip / .war: архив содержит jar вашего проекта и все зависимые jar;
- использовать механизм динамического загрузчика классов (см. Spring, или вы можете легко сделать это самостоятельно), чтобы иметь единственную точку входа в ваш проект (один класс для запуска - см. механизм манифеста в другом ответе), который добавит (динамически) к текущий classpath все остальные необходимые банки.
Таким образом, имея в конце всего лишь манифест и "специальный динамический основной загрузчик классов", вы можете начать свой проект с:
java -jar ProjectMainJar.jar com.stackru.projectName.MainDynamicClassLoaderClass
Я попытался получить самый голосующий ответ здесь, и смог получить флягу. Но программа не работает правильно. Я не знаю, в чем причина. Когда я пытаюсь убежать от Eclipse
, Я получаю другой результат, но когда я запускаю jar из командной строки, я получаю другой результат (он вылетает с ошибкой во время выполнения программы).
У меня было такое же требование, как и у ОП, только у меня было слишком много зависимостей (Maven) для моего проекта. К счастью, единственное решение, которое работало для меня, было то, что использование Eclipse
, Очень просто и очень просто. Это не решение OP, но решение для кого-то, у кого есть подобное требование, но со многими зависимостями Maven,
1) Просто щелкните правой кнопкой мыши папку вашего проекта (в Eclipse) и выберите Export
2) Затем выберите Java
-> Runnable Jar
3) Вам будет предложено выбрать местоположение файла JAR
4) Наконец, выберите класс с методом Main, который вы хотите запустить, и выберите Package dependencies with the Jar file
и нажмите Finish
Если вы хотите, если из самой командной строки. Просто запустите приведенную ниже команду из пути проекта
мвн сборка: сборка
Это также может быть вариантом, вы сможете собрать свой 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>
Добавить в 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-файлы зависимостей.
Maven-Assembly-плагин работал отлично для меня. Я провел часы с плагином maven-dependency-и не мог заставить его работать. Основная причина заключалась в том, что мне пришлось четко определить в разделе конфигурации элементы артефакта, которые должны быть включены, как описано в документации. Там есть пример для случаев, когда вы хотите использовать его как: mvn dependency:copy
, где нет включенных артефактов, но это не работает.