Maven — сгенерировать war и fat jar в одном модуле

#java #maven #jar #executable-jar

#java #maven #jar #исполняемый файл-jar

Вопрос:

Мне нужно сгенерировать war и fat jar (jar со всеми зависимостями) в одном пом.
Я нашел много похожих тем на этом сайте, но все еще есть проблема.

В моем pom я устанавливаю упаковку в war и добавляю maven-war-plugin и maven-assembly-plugin:

 ...
<packaging>war</packaging>
....
<plugins>
  <plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-war-plugin</artifactId>
    <version>2.6</version>
    <configuration>
    </configuration>
  </plugin>
  <plugin>
    <artifactId>maven-assembly-plugin</artifactId>
    <version>2.2-beta-5</version>
    <configuration>
      <descriptorRefs>
        <descriptorRef>jar-with-dependencies</descriptorRef>
      </descriptorRefs>
      <appendAssemblyId>false</appendAssemblyId>
    </configuration>
    <executions>
      <execution>
        <id>make-my-jar-with-dependencies</id>
        <phase>package</phase>
        <goals>
          <goal>single</goal>
        </goals>
      </execution>
    </executions>
  </plugin>
  .... 
  

Обратите внимание на использованную версию maven-assembly-plugin2.2-beta-5. В моих тестах это единственная версия, которая создает правильный файл jar в этой конфигурации. К сожалению, он также выводит много строк «[ИНФОРМАЦИЯ] уже добавлена, пропущена», а процесс сборки занимает слишком много времени.

Если я использую последнюю версию maven-assembly-plugin (2.6), никаких «уже добавленных» информационных отпечатков нет, и сборка выполняется как минимум в 3 раза быстрее, но в отличие от версии 2.2 все мои файлы классов помещаются в /WEB-INF/classes/ folder (должны быть в root),итак, я могу запустить любой основной класс из этого jar. Все классы из зависимостей jar помещены в root, как и ожидалось.

Существуют ли какие-либо параметры конфигурации плагина в последней версии, которые могут помочь создать правильный jar?

Комментарии:

1. Учитывая, что приведенный ниже ответ правильный, ИМХО, вам следует разделить свой проект на несколько модулей. Смешивание war и исполняемого jar может привести к путанице и сложности в обслуживании программного обеспечения

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

3. И я не вижу причин (за исключением, вероятно, технических проблем) разбивать проект на несколько модулей, просто чтобы обеспечить различную упаковку — jar, war, rpm…

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

5. имхо, меньший размер jar не стоит затрат на поддержку нескольких модулей. Обратите внимание, что существуют и другие задачи сборки, например, он также создает rpm, который должен включать оба файла (war и jar)

Ответ №1:

Вам не нужно получать все классы из зависимостей в вашем корневом каталоге. Позвольте плагину сборки творить чудеса. Что касается запуска основного класса, вы можете использовать приведенный ниже код в дополнение к тому, что у вас уже есть.

 <project>
  [...]
  <build>
    [...]
    <plugins>
      <plugin>
        <artifactId>maven-assembly-plugin</artifactId>
        <version>2.6</version>
        <configuration>
          [...]
          <archive>
            <manifest>
              <mainClass>org.sample.App</mainClass>    // specify your main class here.
            </manifest>
          </archive>
        </configuration>
        [...]
      </plugin>
      [...]
</project>
  

Комментарии:

1. 1. в этом jar есть несколько «основных» классов, поэтому я не могу определить его в манифесте и должен предоставить требуемый класс в команде run. 2. чудеса плагина в этом случае не работают, загрузчик классов преобразует каталоги в jar в имена пакетов, которые явно не соответствуют имени пакета, объявленному в файле.

2. Попробуйте использовать это. ` проголосовав против, вы сможете сделать это следующим образом: <build> <outputDirectory>${project.build.directory}/wherever-you-want</outputDirectory> </build> `

3. Я пробовал, это просто изменить место созданного файла, но не его содержимое. Проблема в том, что по какой-то причине после maven-war-plugin последняя версия maven-assembly-plugin принимает ../target/<package> (вместо ../target/classes) в качестве скомпилированного каталога классов. Есть ли параметр для явной установки каталога?