Для чего используется плагин maven-shade, и почему вы хотите переместить java-пакеты?

Я обнаружил, что 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>