Как создать исполняемый JAR-файл со всеми зависимостями в Maven?
Решение: сборка "толстого" JAR с помощью Maven Shade Plugin
Проблема в том, что стандартная команда mvn package создаёт обычный JAR, который содержит только ваш код и ресурсы. Зависимости (например, Apache Commons CSV) остаются отдельными JAR-файлами в локальном репозитории Maven. Чтобы создать единый исполняемый архив, нужно использовать специальный плагин для сборки "толстого" (fat/uber) JAR.
Лучший инструмент для этой задачи — Maven Shade Plugin. Он не только объединяет все зависимости в один JAR, но и решает проблему конфликтов классов (если разные библиотеки содержат одинаковые файлы).
Пошаговая инструкция
Шаг 1: Добавьте плагин в секцию <build><plugins> вашего pom.xml:
<project>
<modelVersion>4.0.0</modelVersion>
<groupId>com.example</groupId>
<artifactId>csv-reader</artifactId>
<version>1.0</version>
<packaging>jar</packaging>
<dependencies>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-csv</artifactId>
<version>1.9.0</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>3.5.1</version>
<configuration>
<!-- Указываем, какой класс является главным -->
<transformers>
<transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
<mainClass>com.example.Main</mainClass>
</transformer>
</transformers>
</configuration>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
Шаг 2: Убедитесь, что ваш основной класс находится в правильном пакете. В вашем примере класс Main находится в пакете по умолчанию (без package ...). Для production-кода так делать не рекомендуется. Лучше добавить пакет:
package com.example;
import org.apache.commons.csv.*;
public class Main {
public static void main(String[] args) throws Exception {
System.out.println("Программа запущена!");
// Ваш код
}
}
Шаг 3: Выполните сборку:
mvn clean package
После этого в папке target появятся два файла:
csv-reader-1.0.jar— обычный JAR (без зависимостей), его можно игнорировать.csv-reader-1.0-shaded.jar— "толстый" JAR со всеми зависимостями. Именно его нужно запускать.
Запуск:
java -jar target/csv-reader-1.0-shaded.jar
Важные моменты:
- Плагин автоматически создаёт манифест с указанием главного класса.
- Если у вас есть ресурсы (например, файлы конфигурации) в зависимостях, плагин объединит их корректно.
- При необходимости можно настроить
<filters>для исключения ненужных файлов (например, лицензий или.classиз тестов).
Этот подход считается стандартом для Java-проектов на Maven. Он простой, надёжный и поддерживается сообществом.
<<Альтернатива: Maven Assembly Plugin
Если вам не нужны продвинутые функции Shade (например, переименование классов для избежания конфликтов), можно использовать более простой Maven Assembly Plugin. Он также создаёт "толстый" JAR, но работает иначе — просто распаковывает все зависимости в один архив.
Пример конфигурации для pom.xml:
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<configuration>
<archive>
<manifest>
<mainClass>com.example.Main</mainClass>
</manifest>
</archive>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
</configuration>
<executions>
<execution>
<id>make-assembly</id>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
</execution>
</executions>
</plugin>
Сборка: mvn clean package. Результат — файл с суффиксом -jar-with-dependencies.jar.
Недостатки по сравнению с Shade:
- Не решает конфликты классов (если две библиотеки содержат одинаковые файлы, один из них будет перезаписан).
- Не объединяет файлы META-INF (например, ServiceLoader-файлы), что может сломать некоторые библиотеки.
Когда использовать: Для простых проектов с небольшим количеством зависимостей, где нет конфликтов. Для серьёзных проектов лучше выбрать Shade Plugin.