Я обнаружил, что maven-shade-plugin используется в ком-то pom.xml. Я никогда не использовал maven-shade-plugin раньше (и я maven n00b), поэтому я попытался понять причину использования этого и того, что он делает. Я посмотрел на maven docs, однако я не могу понять это утверждение: "Этот плагин предоставляет возможность упаковывать артефакт в uber-jar, включая его зависимости и в тень - то есть переименовать - пакеты некоторых зависимостей." Документация на странице не очень удобна для новичков.
Что такое "uber jar?"? Почему кто-то хочет это сделать? Какая точка переименования пакетов зависимостей? Я попытался просмотреть примеры на странице apache maven-shade-plugin, такие как "Выбор содержимого для Uber Jar", но я до сих пор не понимаю, что происходит с "затенением".
Любые указатели на иллюстративные примеры/прецеденты (с объяснением, почему в этом случае требуется затенение - какая проблема это решение). Наконец, когда я должен использовать плагин maven-shade?
Ответ 1
Uber JAR, словом, является JAR, содержащим все.
Обычно в Maven мы полагаемся на управление зависимостями. Артефакт содержит только классы/ресурсы. Maven будет нести ответственность за обнаружение всех артефактов (JAR и т.д.), Что проект зависит от того, когда проект будет построен.
uber-jar - это то, что принимает все зависимости, и извлекает содержимое зависимостей и помещает их с классами/ресурсами самого проекта в один большой JAR. Имея такой uber-jar, это легко выполнить, потому что для запуска вашего приложения вам понадобится только один большой JAR, а не тонны маленьких JAR. Это также облегчает распространение в некоторых случаях.
Просто боковая заметка. Избегайте использования uber-jar в качестве зависимости от Maven, поскольку это разрушает функцию разрешения зависимостей Maven. Обычно мы создаем uber-jar только для финального артефакта для фактического развертывания или для ручного распространения, но не для размещения в репозитории Maven.
Обновление: я только что обнаружил, что не ответил на одну часть вопроса: "Какая точка переименования пакетов зависимостей?". Вот несколько кратких обновлений и, надеюсь, помогут людям, которые имеют схожие вопросы.
Создание uber-jar для простоты развертывания - один из вариантов использования теневого плагина. Существуют также другие распространенные случаи использования, которые включают переименование пакетов.
Например, я разрабатываю библиотеку Foo
, которая зависит от конкретной версии (например, 1.0) библиотеки Bar
. Предполагая, что я не могу использовать другую версию Bar
lib (поскольку изменение API или другие технические проблемы и т.д.). Если я просто объявляю Bar:1.0
как Foo
зависимость в Maven, можно попасть в проблему: проект Qux
зависит от Foo
, а также Bar:2.0
(и он не может использовать Bar:1.0
, потому что Qux
необходимо использовать новую функцию в Bar:2.0
). Вот дилемма: if Qux
использовать Bar:1.0
(код Qux
не работает) или Bar:2.0
(код Foo
не работает)?
Чтобы решить эту проблему, разработчик Foo
может использовать теневой плагин для переименования его использования Bar
, так что все классы в Bar:1.0
jar встроены в Foo
jar, а пакет из встроенных классов Bar
изменяется от com.bar
до com.foo.bar
. Таким образом, Qux
может безопасно зависеть от Bar:2.0
, потому что теперь Foo
больше не зависит от Bar
, и он использует собственную копию "измененного" Bar
, расположенную в другом пакете.
Ответ 2
Недавно я задавался вопросом, почему elasticsearch оттеняет и переносит несколько (но не все) его зависимостей. Здесь объяснение от сопровождающего проекта, @kimchy:
Затеняющая часть является намеренной, затененные библиотеки, которые мы используем в elasticsearch, предназначены для всех целей и целей elasticsearch, используемая версия тесно связана с тем, что раскрывает elasticsearch и как она использует библиотеку на основе внутренних функций того, как библиотека (и что изменения между версиями), netty и guava - отличные примеры.
Кстати, у меня нет проблем с тем, чтобы на самом деле предоставить несколько банок из elasticsearch, один с lucene не заштрихованный, а один с Lucene заштрихован. Не уверен, как это сделать с maven. Я не хочу предоставлять версию, которая не затеняет netty/jackson, например, из-за глубокого скрытого использования elasticsearch с ними (например, использование предстоящего улучшения буферизации с любой предыдущей версией netty, за исключением текущей, будет фактически используют больше памяти по сравнению с использованием значительно меньше).
- https://github.com/elasticsearch/elasticsearch/issues/2091#issuecomment-7156766
И еще один из drewr:
Затенение важно, чтобы наши зависимости (особенно netty, lucene, guava) были близки к нашему коду, чтобы мы могли исправить проблему, даже если отстающий провайдер отстает. Возможно, мы будем распространять модульные версии кода, которые помогут с вашей конкретной проблемой (например, # 2091), но мы не можем просто удалить затененные зависимости в это время. Вы можете создать локальную версию ES для своих целей, пока не появится лучшее решение.
- https://github.com/elasticsearch/elasticsearch/pull/3244#issuecomment-20125452
Итак, это один прецедент. Что касается иллюстративного примера, ниже показано, как maven-shade-plugin используется в elasticsearch pom.xml(v0.90.5). Строки artifactSet::include
инструктируют, какие зависимости затягиваются в uber JAR (в основном, они распаковываются и повторно упаковываются вместе с собственными классами elasticsearch, когда создается целевая сборка elasticsearch. (Если вы этого не знали, JAR файл - это только ZIP файл, содержащий классы программ, ресурсы и т.д. И некоторые метаданные. Вы можете извлечь его, чтобы увидеть, как он складывается.)
Линии relocations::relocation
аналогичны, за исключением того, что в каждом случае они также применяют указанные подстановки к классам зависимостей - в этом случае они подпадают под org.elasticsearch.common
.
Наконец, раздел filters
исключает некоторые вещи из целевого JAR, которые не должны быть там - например, метаданные JAR, ant файлы сборки, текстовые файлы и т.д., которые упакованы с некоторыми зависимостями, но которые не 't принадлежит к uber 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>
Ответ 3
Малое предупреждение
Хотя это не описывает, почему вы хотели бы использовать плагин maven-shade (так как выбранный ответ описывает это довольно хорошо), я хотел бы отметить, что у меня были проблемы с ним. Он изменил JAR (с тех пор как он это сделал), и это вызвало регресс в моем программном обеспечении.
Итак, вместо использования этого (или maven-jarjar-plugin) я использовал двоичный файл JarJar, который работает без проблем.
Я отправляю здесь свое решение, так как мне понадобилось некоторое время, чтобы найти достойное решение.
Файл JARJAR JARJAR Downlaod
Вы можете скачать банку здесь:
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 = jar
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 = jar
mvn install: install-file -Dfile = C:\my-jars\kuku-jackson-databind-2.6.4.jar -DgroupId = io.kuku.dependencies -DartifactId = kuku-jackson-annotations -Dversion = 2.6.4 -Dpackaging = jar
Использование модифицированных JAR в проекте pom
В этом примере это элемент "зависимостей" в проектах 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>