Включая зависимости в банке с Maven
Есть ли способ заставить maven (2.0.9) включить все зависимости в один файл jar?
У меня есть проект, который строится в один файл jar. Я хочу, чтобы классы из зависимостей также были скопированы в банку.
Обновление: Я знаю, что я не могу включить файл jar в файл jar. Я ищу способ распаковать банки, которые указаны как зависимости, и упаковать файлы классов в мою банку.
Ответы
Ответ 1
Вы можете сделать это, используя плагин maven-assembly с дескриптором "jar-with-dependencies". Вот соответствующий фрагмент из одного из наших pom.xml, который делает это:
<build>
<plugins>
<!-- any other plugins -->
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
</execution>
</executions>
<configuration>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
</configuration>
</plugin>
</plugins>
</build>
Ответ 2
В Maven 2 правильный способ сделать это - использовать Плагин сборки Maven2, у которого есть файл предварительно заданного дескриптора для этой цели, который вы можете просто использовать в командной строке :
mvn assembly:assembly -DdescriptorId=jar-with-dependencies
Если вы хотите сделать этот jar исполняемым, просто добавьте основной класс для запуска в конфигурацию плагина:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-assembly-plugin</artifactId>
<configuration>
<archive>
<manifest>
<mainClass>my.package.to.my.MainClass</mainClass>
</manifest>
</archive>
</configuration>
</plugin>
Если вы хотите создать эту сборку как часть обычного процесса сборки, вам следует связать одиночную или директорию-одиночку (цель assembly
должна выполняться ТОЛЬКО из командной строки) в фазу жизненного цикла (package
имеет смысл), что-то вроде этого:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-assembly-plugin</artifactId>
<executions>
<execution>
<id>create-my-bundle</id>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
<configuration>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
...
</configuration>
</execution>
</executions>
</plugin>
Адаптируйте элемент configuration
в соответствии с вашими потребностями (например, с помощью материалов манифеста, как говорится).
Ответ 3
Если вы хотите выполнить исполняемый файл jar, им также необходимо установить основной класс. Таким образом, полная конфигурация должна быть.
<plugins>
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
</execution>
</executions>
<configuration>
<!-- ... -->
<archive>
<manifest>
<mainClass>fully.qualified.MainClass</mainClass>
</manifest>
</archive>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
</configuration>
</plugin>
</plugins>
Ответ 4
Там теневой плагин maven. Его можно использовать для пакета и переименовать зависимости (чтобы опустить проблемы с зависимостями в пути к классам).
Ответ 5
Вы можете использовать только что созданную банку с помощью тега <classifier>
.
<dependencies>
<dependency>
<groupId>your.group.id</groupId>
<artifactId>your.artifact.id</artifactId>
<version>1.0</version>
<type>jar</type>
<classifier>jar-with-dependencies</classifier>
</dependency>
</dependencies>
Ответ 6
Если вы (как и я) не особенно похожи на описанный выше подход jar-with-dependencies,
maven-решение, которое я предпочитаю, - просто построить WAR-проект,
даже если это только отдельное приложение Java, которое вы создаете:
-
Сделайте нормальный jar-проект maven, который будет строить ваш jar файл (без зависимостей).
-
Также настройте военный проект maven (только с пустым файлом src/main/webapp/WEB-INF/web.xml, который позволит избежать предупреждения/ошибки в maven-build), который имеет только ваш jar-проект в качестве зависимости и сделает ваш jar-проект a <module>
под вашим военным проектом. (Этот военный проект - всего лишь простой способ обернуть все ваши зависимости jar файла в zip файл.)
-
Постройте военный проект для создания военного файла.
-
На этапе развертывания просто переименуйте свой .war файл в *.zip и распакуйте его.
Теперь у вас должен быть каталог lib (который вы можете перемещать туда, где вы хотите) с вашей банкой и всеми зависимостями, необходимыми для запуска вашего приложения:
java -cp 'path/lib/*' MainClass
(Подстановочный знак в classpath работает в Java-6 или выше)
Я думаю, что это проще настроить в maven (нет необходимости возиться с плагином сборки), а также дает более четкое представление о структуре приложения (вы увидите номера версий всех зависимых банок в простой просматривать и избегать засорения всего в один jar файл).
Ответ 7
http://fiji.sc/Uber-JAR дает отличное объяснение альтернатив:
Существует три общих метода построения uber-JAR:
- незатушеванная. Распакуйте все файлы JAR, а затем переупакуйте их в один JAR.
- Pro: работает с загрузчиком классов Java по умолчанию.
- Con: Файлы, присутствующие в нескольких файлах JAR с одним и тем же путем (например, META-INF/services/javax.script.ScriptEngineFactory) перезапишет один другой, что приводит к ошибочному поведению.
- Инструменты: сборка Maven Плагин, Classworlds Uberjar
- Затенение. То же, что и unshaded, но переименуйте (т.е. "Shade" ) все пакеты всех зависимостей.
- Pro: работает с загрузчиком класса Java по умолчанию. Избегает некоторых (не всех) конфликтов версий зависимостей.
- Con: Файлы присутствуют в нескольких файлах JAR с одним и тем же путем (например, META-INF/services/javax.script.ScriptEngineFactory) перезапишет один другой, что приводит к ошибочному поведению.
- Инструменты: плагин Maven Shade
- JAR JARs. Последний файл JAR содержит другие JAR файлы, встроенные внутри.
- Pro: предотвращает конфликты версий зависимостей. Все файлы ресурсов сохраняются.
- Con: требуется связать специальный "bootstrap" classloader, чтобы Java могла загружать классы из завернутые файлы JAR. Проблемы с загрузкой класса Debugging становятся более сложными.
- Инструменты: Eclipse JAR File Exporter, One-JAR.
Ответ 8
Мое окончательное решение на Eclipse Luna и m2eclipse:
Custom Classloader (загрузка и добавление в проект, только 5 классов)
: http://git.eclipse.org/c/jdt/eclipse.jdt.ui.git/plain/org.eclipse.jdt.ui/jar%20in%20jar%20loader/org/eclipse/jdt/internal/jarinjarloader/;
этот загрузчик классов очень полезна для однозарядного загрузчика классов и очень быстро;
<project.mainClass>org.eclipse.jdt.internal.jarinjarloader.JarRsrcLoader</project.mainClass>
<project.realMainClass>my.Class</project.realMainClass>
Изменить в JIJConstants "Rsrc-Class-Path" на "Class-Path"
mvn clean dependency: пакет копий-зависимостей
создается банка с зависимостями в папке lib с тонким загрузчиком классов
<build>
<resources>
<resource>
<directory>src/main/java</directory>
<includes>
<include>**/*.java</include>
<include>**/*.properties</include>
</includes>
</resource>
<resource>
<directory>src/main/resources</directory>
<filtering>true</filtering>
<includes>
<include>**/*</include>
</includes>
<targetPath>META-INF/</targetPath>
</resource>
<resource>
<directory>${project.build.directory}/dependency/</directory>
<includes>
<include>*.jar</include>
</includes>
<targetPath>lib/</targetPath>
</resource>
</resources>
<pluginManagement>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<configuration>
<archive>
<manifest>
<addClasspath>true</addClasspath>
<mainClass>${project.mainClass}</mainClass>
<classpathPrefix>lib/</classpathPrefix>
</manifest>
<manifestEntries>
<Rsrc-Main-Class>${project.realMainClass} </Rsrc-Main-Class>
<Class-Path>./</Class-Path>
</manifestEntries>
</archive>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<executions>
<execution>
<id>copy-dependencies</id>
<phase>package</phase>
<goals>
<goal>copy-dependencies</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</pluginManagement>
</build>
Ответ 9
<!-- Method 1 -->
<!-- Copy dependency libraries jar files to a separated LIB folder -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<configuration>
<outputDirectory>${project.build.directory}/lib</outputDirectory>
<excludeTransitive>false</excludeTransitive>
<stripVersion>false</stripVersion>
</configuration>
<executions>
<execution>
<id>copy-dependencies</id>
<phase>package</phase>
<goals>
<goal>copy-dependencies</goal>
</goals>
</execution>
</executions>
</plugin>
<!-- Add LIB folder to classPath -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>2.4</version>
<configuration>
<archive>
<manifest>
<addClasspath>true</addClasspath>
<classpathPrefix>lib/</classpathPrefix>
</manifest>
</archive>
</configuration>
</plugin>
<!-- Method 2 -->
<!-- Package all libraries classes into one runnable jar -->
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
</execution>
</executions>
<configuration>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
</configuration>
</plugin>
Ответ 10
Отложив Maven в сторону, вы можете поместить библиотеки JAR в главную банку, но вам нужно будет использовать свой собственный загрузчик классов.
Проверьте этот проект: One-JAR текст ссылки
Ответ 11
Это сообщение может быть немного старым, но у меня также была такая же проблема в последнее время. Первое решение, предложенное Джоном Стауффером, является хорошим, но у меня были некоторые проблемы, так как я работаю над этим spring. Я использую j87-зависимые jars файлы с некоторыми файлами свойств и объявлением xml-schemas, которые имеют одинаковые пути и имена. Хотя эти баночки берутся из одних и тех же версий, maven-goal jar-with-dependencies переписывал файл theses с последним найденным файлом.
В конце концов, приложение не смогло запуститься, так как банки spring не смогли найти правильные файлы свойств. В этом случае решение, предлагаемое Rop, решило мою проблему.
Также с тех пор существует проект spring -boot. У этого есть очень классный способ управлять этой проблемой, предоставляя цель maven, которая перегружает цель пакета и предоставляет свой собственный загрузчик классов. См. spring -boots Справочное руководство
Ответ 12
Посмотрите на этот ответ:
Я создаю установщик, который работает как файл JAR Java, и ему нужно распаковать WAR и JAR файлы в соответствующие места в каталоге установки. Плагин зависимостей можно использовать в фазе пакета с целью копирования, и он загрузит любые файлы в репозитории Maven (включая файлы WAR) и напишет их там, где они вам понадобятся. Я сменил выходной каталог на ${project.build.directory}/classes, а затем конечным результатом является то, что обычная задача JAR включает мои файлы в порядке. Затем я смогу извлечь их и записать в каталог установки.
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<executions>
<execution>
<id>getWar</id>
<phase>package</phase>
<goals>
<goal>copy</goal>
</goals>
<configuration>
<artifactItems>
<artifactItem>
<groupId>the.group.I.use</groupId>
<artifactId>MyServerServer</artifactId>
<version>${env.JAVA_SERVER_REL_VER}</version>
<type>war</type>
<destFileName>myWar.war</destFileName>
</artifactItem>
</artifactItems>
<outputDirectory>${project.build.directory}/classes</outputDirectory>
</configuration>
</execution>
</executions>
Ответ 13
Спасибо
Я добавил ниже фрагмента в файле POM.xml, и проблема с Mp решена и
создайте файл жира, содержащий все зависимые баночки.
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
</execution>
</executions>
<configuration>
<descriptorRefs>
<descriptorRef>dependencies</descriptorRef>
</descriptorRefs>
</configuration>
</plugin>
</plugins>