В том числе зависимостей в jar с помощью Maven



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



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



обновление: Я знаю, что я не могу просто включить файл jar в файл jar. Я ищу способ распаковать банки, которые указаны как зависимости, и упаковать файлы классов в мою банку.

1002   13  

13 ответов:

вы можете сделать это с помощью плагина 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>

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

если вы хотите создать эту сборку как часть обычного процесса сборки, вы должны привязать один или цель (the assembly цель должна запускаться только из командной строки) на этапе жизненного цикла (package имеет смысл), что-то вроде этого:

<plugin>
  <groupId>org.apache.maven.plugins</groupId>
  <artifactId>maven-assembly-plugin</artifactId>
  <executions>
    <execution>
      <id>create-my-bundle</id>
      <phase>package</phase>
      <goals>
        <goal>single</goal>
      </goals>
      <configuration>
        <descriptorRefs>
          <descriptorRef>jar-with-dependencies</descriptorRef>
        </descriptorRefs>
        ...
      </configuration>
    </execution>
  </executions>
</plugin>

адаптация configuration элемент в соответствии с вашими потребностями (например, с манифестом вещи, как говорят).

Если вы хотите сделать исполняемый файл jar, им нужно установить основной класс тоже. Так что полная конфигурация должна быть.

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

здесь shade maven plugin. Его можно использовать для пакета и переименовать зависимости (чтобы опустить проблемы зависимости на пути к классу).

Если вы (как я) не особенно нравится jar-with-dependencies подход, описанный выше, maven-решение, которое я предпочитаю, - это просто построить военный проект, даже если это всего лишь автономное приложение java, которое вы создаете:

  1. сделайте обычный jar-проект maven, который построит ваш jar-файл (без зависимостей).

  2. кроме того, установите Maven war-project (только с пустым src / main/webapp/WEB-INF / web.xml файл, который позволит избежать предупреждения / ошибки в Maven-build), который имеет только ваш jar-проект в качестве зависимости и делает ваш jar-проект a <module> под вашим военным проектом. (Этот военный проект-это всего лишь простой трюк, чтобы обернуть все ваши зависимости jar-файла в zip-файл.)

  3. создайте war-проект для создания war-файла.

  4. на этапе развертывания просто переименуйте ваш .война-файл к *.ЗИП и распаковать его.

теперь у вас должен быть lib-каталог (который вы можете перемещать туда, куда хотите) с вашим jar и всеми зависимостями, необходимыми для запуска вашего приложения:

java -cp 'path/lib/*' MainClass

(подстановочный знак в classpath работает в Java-6 или выше)

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

вы можете использовать вновь созданную банку с помощью <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>

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

существует три распространенных метода построения uber-JAR:

  1. Незаштрихованной. Распакуйте все файлы JAR, а затем упакуйте их в одну банку.
    • Pro: работает с загрузчиком классов Java по умолчанию.
    • Con: файлы, присутствующие в нескольких файлах JAR с одним и тем же путем (например, META-INF / services / javax.скрипт.ScriptEngineFactory) перезапишет один другой, что приводит к ошибочному поведению.
    • Инструменты: Сборка Maven Плагин, Classworlds Uberjar
  2. закрасить. То же самое, что и unshaded, но переименовать (т. е. "затенить") все пакеты всех зависимостей.
    • Pro: работает с загрузчиком классов Java по умолчанию. Позволяет избежать некоторых (не всех) конфликтов версий зависимостей.
    • Con: Файлы присутствует в нескольких файлах JAR с тот же путь (например, META-INF / services / javax.скрипт.ScriptEngineFactory) перезапишет один другой, что приводит к ошибочному поведению.
    • Инструменты: Maven Shade Plugin
  3. банка банок. Последний файл JAR содержит другие файлы JAR, встроенные в него.
    • Pro: позволяет избежать столкновений версий зависимостей. Все файлы ресурсов сохраняются.
    • Con: необходимо связывать специальный загрузчик классов "bootstrap" для загрузки Java классы завернутый JAR-файлы. Отладка проблем загрузчика классов становится более сложной.
    • инструменты: Eclipse Jar File Exporter, One-JAR.

мое окончательное решение по Eclipse Luna и m2eclipse: Пользовательский загрузчик классов (скачать и добавить в проект только 5 классов ) :http://git.eclipse.org/c/jdt/eclipse.jdt.ui.git/plain/org.eclipse.jdt.ui/jar%20in%20jar%20loader/org/eclipse/jdt/internal/jarinjarloader/; этот загрузчик классов очень лучший из одноячеечного загрузчика классов и очень быстрый;

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

изменить в JIJConstants "Rsrc-Class-Path" на "Class-Path"
mvn чистый зависимость: copy-dependencies package
создается jar с зависимостями в папке 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>
        <!-- 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>            

отложив Maven в сторону, вы можете поместить библиотеки JAR в основную банку, но вам нужно будет использовать свой собственный загрузчик классов.

проверьте этот проект: One-JAR текст ссылки

этот пост может быть немного старым, но у меня тоже была такая же проблема в последнее время. Первое решение, предложенное Джоном Стаффером, является хорошим, но у меня были некоторые проблемы, поскольку я работаю этой весной. Весенние зависимые банки, которые я использую, имеют некоторые файлы свойств и объявление xml-схем, которые имеют одни и те же пути и имена. Хотя эти банки происходят из тех же версий,jar-with-dependencies мавен-цель была перезапись файла с тезисами последнего найденного файла.

In в конце концов, приложение не удалось запустить, так как весенние банки не смогли найти правильные файлы свойств. В этом случае решение, предложенное Rop, решило мою проблему.

также с тех пор, проект spring-boot теперь существует. Он имеет очень крутой способ справиться с этой проблемой, предоставляя цель maven, которая перегружает цель пакета и предоставляет свой собственный загрузчик классов. Смотрите справочник по пружинным ботинкам

взгляните на этот ответ:

Я создаю установщик, который работает как Java JAR-файл, и ему нужно распаковать файлы WAR и JAR в соответствующие места в каталоге установки. Плагин зависимостей можно использовать на этапе пакета с целью копирования, и он загрузит любой файл в репозитории Maven (включая файлы WAR) и запишет их там, где они вам понадобятся. Я изменил выходной каталог на ${project.строить.каталог} / классы, а затем конец результат заключается в том, что обычная задача 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>

спасибо Я добавил ниже фрагмент в POM.xml-файл и Mp проблема решена и создать файл fat jar, который включает все зависимые банки.

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

Comments

    Ничего не найдено.