Для чего используется плагин maven-shade-plugin и почему вы хотите переместить пакеты Java?
Я обнаружил, что maven-shade-plugin используется в чьем-то файле pom.xml. Я никогда раньше не использовал maven-shade-plugin (и я Maven n00b), поэтому я попытался понять причину использования этого и то, что он делает.
Я посмотрел на документы Maven, однако не могу понять это утверждение:
"Этот плагин предоставляет возможность упаковать артефакт в uber-jar, включая его зависимости, и затемнить - то есть переименовать - пакеты некоторых зависимостей". Документация на странице не выглядит очень удобной для новичков.
Что такое "Uber Jar"? Почему кто-то хочет сделать один? Какой смысл переименовывать пакеты зависимостей? Я попытался просмотреть примеры на странице apache maven-shade-plugin, такие как "Выбор содержимого для Uber Jar", но до сих пор не могу понять, что происходит с "затенением".
Будем благодарны за любые указатели на иллюстративные примеры / варианты использования (с объяснением того, почему в этом случае требуется затенение - какую проблему он решает). Наконец, когда я должен использовать плагин maven-shade-plugin?
3 ответа
Короче говоря, Uber JAR - это JAR, содержащий все.
Обычно в Maven мы полагаемся на управление зависимостями. Артефакт содержит только свои классы / ресурсы. Maven будет нести ответственность за обнаружение всех артефактов (JAR и т. Д.), Которые будут выполняться в зависимости от проекта.
Uber-jar - это то, что берет все зависимости, извлекает содержимое зависимостей и помещает их вместе с классами / ресурсами самого проекта в один большой JAR-файл. Имея такой uber-jar, его легко выполнить, потому что для запуска вашего приложения вам понадобится всего один большой JAR вместо множества маленьких JAR. Это также облегчает распространение в некоторых случаях.
Просто примечание. Избегайте использования uber-jar в качестве зависимости Maven, так как это разрушает функцию разрешения зависимостей в Maven. Обычно мы создаем uber-jar только для конечного артефакта для фактического развертывания или для ручного распространения, но не для помещения в репозиторий Maven.
Обновление: я только что обнаружил, что не ответил ни на одну часть вопроса: "Какой смысл переименовывать пакеты зависимостей?". Вот некоторые краткие обновления и, надеюсь, помогут людям, имеющим схожий вопрос.
Создание Uber-JAR для простоты развертывания является одним из вариантов использования плагина Shade. Есть и другие распространенные случаи использования, которые включают переименование пакетов.
Например, я разрабатываю Foo
библиотека, которая зависит от конкретной версии (например, 1.0) Bar
библиотека. Предполагая, что я не могу использовать другую версию Bar
lib (из-за изменения API или других технических проблем и т. д.). Если я просто заявляю Bar:1.0
как Foo
зависимость в Maven, можно попасть в проблему: Qux
проект зависит от Foo
, а также Bar:2.0
(и он не может использовать Bar:1.0
так как Qux
необходимо использовать новую функцию в Bar:2.0
). Вот дилемма: следует Qux
использование Bar:1.0
(который Qux
код не будет работать) или Bar:2.0
(который Foo
код не сработает)?
Чтобы решить эту проблему, разработчик Foo
можете использовать плагин Shade, чтобы переименовать его использование Bar
так что все классы в Bar:1.0
банка встроена в Foo
банка и упаковка Bar
классы изменены с com.bar
в com.foo.bar
, Тем самым, Qux
может безопасно зависит от Bar:2.0
потому что сейчас Foo
больше не зависит от Bar
и использует собственную копию "измененного" Bar
находится в другой упаковке.
Я недавно задавался вопросом, почему эластичный поиск затеняет и перемещает некоторые (но не все) его зависимости. Вот объяснение от сопровождающего проекта, kimchy:
Затенение является преднамеренным, затененные библиотеки, которые мы используем в эластичном поиске, предназначены для всех целей и целей части эластичного поиска, используемая версия тесно связана с тем, что демонстрирует эластичный поиск, и как она использует библиотеку, основываясь на внутренних принципах работы библиотеки (и что изменения между версиями), нетти и гуава являются отличными примерами.
Кстати, у меня нет проблем с тем, чтобы на самом деле предоставить несколько банок с эластичным поиском, один с люценом, не затененный, а другой с люценом. Не уверен, как это сделать с Mave n, хотя. Я не хочу предоставлять версию, которая не затеняет нетти / джексона, например, из-за глубокого запугивания, которое имеет с ними эластичный поиск (например, использование предстоящего улучшения буферизации с любой предыдущей версией netty, за исключением текущей, будет на самом деле использовать больше памяти по сравнению с использованием значительно меньше).
- https://github.com/elasticsearch/elasticsearch/issues/2091
И еще один здесь от drewr:
Затенение важно, чтобы наши зависимости (в частности, netty, lucene, guava) были близки к нашему коду, чтобы мы могли исправить проблему, даже если вышестоящий провайдер отстает. Возможно, мы будем распространять модульные версии кода, которые помогут решить вашу конкретную проблему (например, #2091), но в настоящее время мы не можем просто удалить затененные зависимости. Вы можете создать локальную версию ES для своих целей, пока не найдете лучшего решения.
- https://github.com/elasticsearch/elasticsearch/pull/3244
Итак, это один из вариантов использования. Что касается иллюстративного примера, то ниже показано, как mave n-shade-plugin используется в файле pse.xml эластичного поиска (v0.90.5). artifactSet::include
линии указывают ему, какие зависимости нужно вставить в UAR-JAR-файл (в основном они распаковываются и переупаковываются вместе с собственными классами эластичного поиска, когда создается целевой Jar-архив эластичного поиска. (Если вы этого еще не знали, файл JAR просто ZIP-файл, содержащий классы программы, ресурсы и т. д., а также некоторые метаданные. Вы можете извлечь один из них, чтобы увидеть, как он составлен.)
relocations::relocation
линии похожи, за исключением того, что в каждом случае они также применяют указанные замены к классам зависимости - в этом случае, приводя их к org.elasticsearch.common
,
Наконец то filters
section исключает некоторые вещи из целевого JAR, которых там быть не должно - такие как метаданные JAR, файлы сборки ant, текстовые файлы и т. д., которые упакованы с некоторыми зависимостями, но не принадлежат UAR JAR.
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>2.1</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
</execution>
</executions>
<configuration>
<minimizeJar>true</minimizeJar>
<artifactSet>
<includes>
<include>com.google.guava:guava</include>
<include>net.sf.trove4j:trove4j</include>
<include>org.mvel:mvel2</include>
<include>com.fasterxml.jackson.core:jackson-core</include>
<include>com.fasterxml.jackson.dataformat:jackson-dataformat-smile</include>
<include>com.fasterxml.jackson.dataformat:jackson-dataformat-yaml</include>
<include>joda-time:joda-time</include>
<include>io.netty:netty</include>
<include>com.ning:compress-lzf</include>
</includes>
</artifactSet>
<relocations>
<relocation>
<pattern>com.google.common</pattern>
<shadedPattern>org.elasticsearch.common</shadedPattern>
</relocation>
<relocation>
<pattern>gnu.trove</pattern>
<shadedPattern>org.elasticsearch.common.trove</shadedPattern>
</relocation>
<relocation>
<pattern>jsr166y</pattern>
<shadedPattern>org.elasticsearch.common.util.concurrent.jsr166y</shadedPattern>
</relocation>
<relocation>
<pattern>jsr166e</pattern>
<shadedPattern>org.elasticsearch.common.util.concurrent.jsr166e</shadedPattern>
</relocation>
<relocation>
<pattern>org.mvel2</pattern>
<shadedPattern>org.elasticsearch.common.mvel2</shadedPattern>
</relocation>
<relocation>
<pattern>com.fasterxml.jackson</pattern>
<shadedPattern>org.elasticsearch.common.jackson</shadedPattern>
</relocation>
<relocation>
<pattern>org.joda</pattern>
<shadedPattern>org.elasticsearch.common.joda</shadedPattern>
</relocation>
<relocation>
<pattern>org.jboss.netty</pattern>
<shadedPattern>org.elasticsearch.common.netty</shadedPattern>
</relocation>
<relocation>
<pattern>com.ning.compress</pattern>
<shadedPattern>org.elasticsearch.common.compress</shadedPattern>
</relocation>
</relocations>
<filters>
<filter>
<artifact>*:*</artifact>
<excludes>
<exclude>META-INF/license/**</exclude>
<exclude>META-INF/*</exclude>
<exclude>META-INF/maven/**</exclude>
<exclude>LICENSE</exclude>
<exclude>NOTICE</exclude>
<exclude>/*.txt</exclude>
<exclude>build.properties</exclude>
</excludes>
</filter>
</filters>
</configuration>
</plugin>
</plugins>
Я думаю, что одним из примеров необходимости "затененной" банки является функция AWS Lambda. Кажется, что они позволяют загружать только 1 банку, а не всю коллекцию файлов.jar, как в типичном файле.war. Итак, создание единого файла.jar со всеми зависимостями проекта позволяет вам это сделать.
Небольшое предупреждение
Хотя это не описывает, почему кто-то хотел бы использовать плагин maven-shade-plugin (так как выбранный ответ описывает его довольно хорошо), я хотел бы отметить, что у меня были проблемы с ним. Это изменило JAR (так как это то, что он делает), и это вызвало регресс в моем программном обеспечении.
Таким образом, вместо того, чтобы использовать это (или maven-jarjar-plugin), я использовал бинарный файл JarJar, который, кажется, работает без проблем.
Я публикую здесь свое решение, так как мне потребовалось некоторое время, чтобы найти достойное решение.
Загрузите JAR-файл JarJar
Вы можете скачать банку отсюда: https://code.google.com/p/jarjar/ В левом меню у вас есть ссылка для его загрузки.
Как использовать JarJar для перемещения классов JAR из одного пакета в другой
В этом примере мы изменим пакет с "com.fasterxml.jackson" на "io.kuku.dependencies.com.fasterxml.jackson". - Исходный JAR называется "jackson-databind-2.6.4.jar", а новый модифицированный (целевой) JAR называется "kuku-jackson-databind-2.6.4.jar". - JAR-файл "jarjar" находится в версии 1.4
Создайте файл "rules.txt". Содержимое файла должно быть (смотрите точку перед символом "@"): правило com.fasterxml.jackson.** io.kuku.dependencies.com.fasterxml.jackson.@1
Выполните следующую команду: java -jar jarjar-1.4.jar process rules.txt jackson-databind-2.6.4.jar kuku-jackson-databind-2.6.4.jar
Установка модифицированных JAR-файлов в локальный репозиторий
В этом случае я устанавливаю 3 файла, расположенных в папке "c:\my-jars\".
mvn install: install-file -Dfile = C: \ my-jars \ kuku-jackson-annotations-2.6.4.jar -DgroupId = io.kuku.dependencies -DartifactId = kuku-jackson-annotations -Dversion=2.6.4 -Dpackaging= баночка
mvn install:install-file -Dfile=C:\my-jars\kuku-jackson-core-2.6.4.jar -DgroupId=io.kuku.dependencies -DartifactId=kuku-jackson-core -Dversion=2.6.4 -Dpackaging= баночка
mvn install:install-file -Dfile=C:\my-jars\kuku-jackson-databind-2.6.4.jar -DgroupId=io.kuku.dependencies -DartifactId= Куку-Джексон-аннотации -Dversion=2.6.4 -Dpackaging= баночка
Использование модифицированных файлов JAR в pom проекта
В этом примере это элемент "dependencies" в проектах pom:
<dependencies>
<!-- ================================================== -->
<!-- kuku JARs -->
<!-- ================================================== -->
<dependency>
<groupId>io.kuku.dependencies</groupId>
<artifactId>kuku-jackson-annotations</artifactId>
<version>2.6.4</version>
</dependency>
<dependency>
<groupId>io.kuku.dependencies</groupId>
<artifactId>kuku-jackson-core</artifactId>
<version>2.6.4</version>
</dependency>
<dependency>
<groupId>io.kuku.dependencies</groupId>
<artifactId>kuku-jackson-databind</artifactId>
<version>2.6.4</version>
</dependency>
</dependencies>