Создание толстой банки с использованием maven

118

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

Я слышал, что это можно сделать с помощью maven-assembly-plug-in, но не понимаю как. Может кто-нибудь указать мне на несколько примеров.

Прямо сейчас я использую толстую банку, чтобы связать последнюю банку. Я хочу добиться того же, используя maven.

Бьянка
источник

Ответы:

144

Примечание. Если вы используете приложение с весенней загрузкой, прочтите конец ответа.

Добавьте следующий плагин в свою pom.xml Последнюю версию можно найти по адресу

...
<build>
    <plugins>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-assembly-plugin</artifactId>
            <version>CHOOSE LATEST VERSION HERE</version>
            <configuration>
                <descriptorRefs>
                    <descriptorRef>jar-with-dependencies</descriptorRef>
                </descriptorRefs>
            </configuration>
            <executions>
                <execution>
                    <id>assemble-all</id>
                    <phase>package</phase>
                    <goals>
                        <goal>single</goal>
                    </goals>
                </execution>
            </executions>
        </plugin>
    </plugins>
</build>
...

После настройки этого подключаемого модуля при запуске mvn packageбудут созданы два jar-файла: один, содержащий только классы проекта, и второй толстый jar-файл со всеми зависимостями с суффиксом «-jar-with-dependencies».

если вы хотите правильную classpathнастройку во время выполнения, также добавьте следующий плагин

<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>
    <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>
Джигар Джоши
источник
1
Текущая версия этого плагина - 2.4
guerda
13
Теперь это не рекомендуется, и вместо него следует использовать maven-shade-plugin. См. Ответ @phlogratos: stackoverflow.com/a/16222965/274350 .
Ричард Нейш
2
Может ли maven-assembly-plugin минимизировать размер толстой банки?
мая,
1
@Richard Где вы видите, что он устарел? Я ничего не нашел здесь maven.apache.org/plugins/maven-assembly-plugin
user3833308
3
@ user3833308 «устаревший» может быть неправильным словом, но в документации на maven.apache.org/plugins/maven-assembly-plugin говорится: «Если ваш проект хочет упаковать артефакт в uber-jar, подключаемый модуль сборки предоставляет только базовые поддержка. Для большего контроля используйте плагин Maven Shade ".
Ричард Нейш
55

Вы можете использовать maven-shade-plugin .

После настройки плагина тени в вашей сборке команда mvn packageсоздаст одну единую банку со всеми объединенными в нее зависимостями.

phlogratos
источник
9
Теперь это правильный способ сделать это. В документации maven-assembly-plugin говорится: «Если ваш проект хочет упаковать ваш артефакт в uber-jar, подключаемый модуль сборки обеспечивает только базовую поддержку. Для большего контроля используйте подключаемый модуль Maven Shade».
Ричард Нейш
Но как мне взять этот единственный .jar и использовать его для публикации?
DanGordon
42

Может быть, вы хотите maven-shade-pluginсвязать зависимости, свести к минимуму неиспользуемый код и скрыть внешние зависимости, чтобы избежать конфликтов.

<build>
    <plugins>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-shade-plugin</artifactId>
            <version>3.1.1</version>
            <executions>
                <execution>
                    <phase>package</phase>
                    <goals>
                        <goal>shade</goal>
                    </goals>
                    <configuration>
                        <minimizeJar>true</minimizeJar>
                        <createDependencyReducedPom>true</createDependencyReducedPom>
                        <dependencyReducedPomLocation>
                            ${java.io.tmpdir}/dependency-reduced-pom.xml
                        </dependencyReducedPomLocation>
                        <relocations>
                            <relocation>
                                <pattern>com.acme.coyote</pattern>
                                <shadedPattern>hidden.coyote</shadedPattern>
                            </relocation>
                        </relocations>
                    </configuration>
                </execution>
            </executions>
        </plugin>
    </plugins>
</build>

Ссылки:

ggrandes
источник
Если встретится Provider org.apache.xerces.jaxp.SAXParserFactoryImpl not found, просто удалите <minimizeJar>true</minimizeJar>.
koppor 06
Если вы получите исключение «java.lang.SecurityException: недействительный дайджест файла подписи для исключения основных атрибутов манифеста», то это добавление к указанному выше разделу конфигурации поможет: stackoverflow.com/a/6743609/38368
Дэнни Варод
12

фактически, добавив

<archive>
   <manifest>
    <addClasspath>true</addClasspath>
    <packageName>com.some.pkg</packageName>                     
    <mainClass>com.MainClass</mainClass>
  </manifest>
</archive>

объявление в maven-jar-plugin не добавляет для меня запись основного класса в файл манифеста. Мне пришлось добавить его в maven-assembly-plugin, чтобы получить это в манифесте

Амит Чаубал
источник
5

Вы можете использовать плагин onejar-maven-plugin для упаковки. По сути, он собирает ваш проект и его зависимости как одну банку, включая не только файл jar вашего проекта, но и все внешние зависимости как «банку из банок», например

<build>
    <plugins>
        <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>
    </plugins>
</build>

Примечание 1. Параметры конфигурации доступны на домашней странице проекта .

Примечание 2: по той или иной причине проект onejar-maven-plugin не публикуется на Maven Central. Однако jolira.com отслеживает исходный проект и публикует его с groupId com.jolira.

matsev
источник
Можно ли выбрать зависимости, которые вы хотите упаковать? Например, если a.jar и b.jar являются внешними банками, и я хочу упаковать только a.jar в финальную банку, возможно ли это / можно настроить?
bianca
Я также вижу, что в финальную банку помещают только одну банку. Это значительно увеличило размер последней банки. Можно ли выбрать внешние банки, которые вы собираетесь включить в финальную банку? Вот логи из одной банки: pastebin.com/UwniQJ2X
bianca
Я не знаю, можете ли вы настроить то, что включено, или нет. По сути, one-jar включает в себя все зависимости, указанные в вашем проекте, включая транзитивные зависимости, так что да, финальный jar-файл, вероятно, станет большим, если у вас много зависимостей. Некоторые накладные расходы будут добавлены из-за использования одной банки, чтобы Java работала со структурой «баночка из банок».
matsev
2

Альтернативой является использование плагина maven shade для создания файла uber-jar.

<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-shade-plugin</artifactId>
    <version> Your Version Here </version>
    <configuration>
            <!-- put your configurations here -->
    </configuration>
    <executions>
            <execution>
                    <phase>package</phase>
                    <goals>
                            <goal>shade</goal>
                    </goals>
            </execution>
    </executions>
</plugin>
Станислав
источник