Для чего используется Maven-shade-plugin и почему вы хотите переместить пакеты Java?

Я нашел Maven-shade-плагин, используемый в чьем-то pom.XML. Я никогда не использовал Maven-shade-plugin раньше (и я Maven n00b), поэтому я попытался понять причину использования этого и что он делает.

Я посмотрел на Maven docs, но я не могу понять это утверждение:

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

Что такое " Uber jar?- Зачем кому-то понадобилось его делать? Какой смысл переименовывать пакеты зависимостей? Я попытался пройти примеры на странице apache Maven-shade-plugin, такие как" выбор содержимого для Uber Jar", но я все еще не могу понять, что происходит с "затенением"."

любые указатели на иллюстративные примеры / варианты использования (с объяснение того, почему затенение было необходимо в этом случае - какая проблема это решение) было бы оценено. Наконец, когда я должен использовать Maven-shade-plugin?

3 ответов


Uber JAR, короче говоря, это Банка, содержащая все.

обычно в Maven мы полагаемся на управление зависимостями. Артефакт содержит только классы/ресурсы самого себя. Maven будет нести ответственность, чтобы найти все артефакты (банки и т. д.), что проект в зависимости от того, когда проект будет построен.

uber-jar-это то, что принимает все зависимости и извлекает содержимое зависимостей и помещает их в классы / ресурсы самого проекта, в одна большая банка. Имея такой uber-jar, его легко выполнить, потому что вам понадобится только одна большая банка вместо тонны маленьких банок для запуска вашего приложения. В некоторых случаях это также облегчает распределение.

просто Примечание. Избегайте использования uber-jar в качестве зависимости Maven, так как это разрушает функцию разрешения зависимостей Maven. Обычно мы создаем uber-jar только для конечного артефакта для фактического развертывания или для ручного распространения, но не для сдачи Maven хранилище.


Update: я только что обнаружил, что не ответил на одну часть вопроса: "Какой смысл переименовывать пакеты зависимостей?". Вот некоторые краткие обновления и, надеюсь, помогут людям, имеющим аналогичный вопрос.

создание uber-jar для простоты развертывания является одним из вариантов использования Shade plugin. Существуют также другие распространенные случаи использования, которые включают переименование пакетов.

например, я разрабатываю Foo библиотека, что зависит от конкретной версии (например, 1.0)Bar библиотека. Предполагая, что я не могу использовать другую версию Bar lib (потому что изменение API или другие технические проблемы и т. д.). Если я просто объявлю Bar:1.0 as Fooзависимость в Maven, можно попасть в проблему: a Qux проект зависит от Foo, а также Bar:2.0 (и он не может использовать Bar:1.0, потому что Qux нужно использовать новую функцию в Bar:2.0). Вот дилемма: должен Qux использовать Bar:1.0 (который Quxкод не будет работать) или Bar:2.0 (где Fooкод не будет работать)?

чтобы решить эту проблему, разработчик Foo можно использовать Shade plugin для переименования его использования Bar, Так что все классы в Bar:1.0 jar встроены в Foo jar и пакет встроенного Bar классы изменены с com.bar to com.foo.bar. Поступая так,Qux может безопасно зависит от Bar:2.0 потому что теперь Foo больше не зависит от Bar, и это использование собственной копии "изменено"Bar находится в другом пакете.


недавно мне было интересно, почему Elasticsearch оттеняет и перемещает несколько (но не все) его зависимостей. Вот объяснение от сопровождающего проекта,@kimchy:

часть затенения преднамеренна, затененные библиотеки, которые мы используем в elasticsearch, для всех намерений и целей являются частью elasticsearch, используемая версия тесно связана с тем, что Elasticsearch предоставляет и как он использует библиотеку на основе внутренних как работает библиотека (и что изменения между версиями), Нетти и гуава являются отличными примерами.

кстати, у меня нет проблем с предоставлением нескольких банок 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 используется в POM elasticsearch.XML (с версии v0.90.5). The artifactSet::include линии инструктируют его, какие зависимости тянуть в Uber JAR (в основном, они распаковываются и повторно упаковываются вместе с собственными классами elasticsearch, когда создается целевой Elasticsearch jar. (Если вы еще не знали об этом, файл JAR-это просто ZIP-файл, содержащий классы, ресурсы и т. д. и некоторые метаданные. Вы можете извлечь один, чтобы увидеть как это сложить.)

на relocations::relocation строки похожи, за исключением того, что в каждом случае они также применяют указанные подстановки к классам зависимостей - в этом случае, подводя их под org.elasticsearch.common.

наконец-то filters раздел исключает некоторые вещи из целевой банки, которые не должны быть там - например, метаданные JAR, файлы сборки ant, текстовые файлы и т. д. это упаковано с некоторыми зависимостями, но которые не принадлежат в банке uber.

<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>


небольшое предупреждение

хотя это не описывает, почему хотелось бы использовать Maven-shade-plugin (так как выбранный ответ описывает его довольно хорошо), я хотел бы отметить, что у меня были проблемы с ним. Он изменил банку (с тех пор, что она делает), и это вызвало регрессию в моем программном обеспечении.

Итак, вместо того, чтобы использовать это (или Maven-jarjar-plugin), я использовал двоичный файл JarJar, который, похоже, работает без проблем.

Я размещаю здесь мой решение, так как мне потребовалось некоторое время, чтобы найти достойное решение.


файл JAR Downlaod Джарджара

вы можете скачать jar-файл отсюда: https://code.google.com/p/jarjar/ В левом меню у вас есть ссылка, чтобы скачать ее.


Как использовать JarJar для перемещения классов банки из одного пакета в другой

в этом примере мы будем изменять пакет из " com.fasterxml.Джексон" в "Ио.кюкю.зависимостей.ком.fasterxml.Джексона". - Исходная банка называется " jackson-databind-2.6.4.jar "и новая модифицированная (целевая) банка называется" kuku-jackson-databind-2.6.4.сосуд." - Файл JAR" jarjar " находится в версии 1.4

  1. создать "правила.txt-файл. Содержимое файла должно быть (смотрите период перед символом" @ ): правило com.fasterxml.Джексон.** io.kuku.dependencies.com.fasterxml.jackson.@1

  2. выполните следующие действия команда: java-jar jarjar-1.4.правила процесса jar.txt jackson-databind-2.6.4.банку Куку-Джексон-привязку-2.6.4.Джар


установка измененных банок в локальный репозиторий

в этом случае я устанавливаю 3 файла, расположенные на "c:\my-jars \" папка.

МВН установки:Установка-файл -единственный способ иметь установленный=с:\мои-банки\Куку-Джексон-аннотации-2.6.4.jar-DgroupId=io.кюкю.зависимости-DartifactId=kuku-jackson-аннотации-Dversion=2.6.4 - Dpackaging=jar

mvn install:install-file-Dfile=C:\my-jars\kuku-jackson-core-2.6.4.jar-DgroupId=io.кюкю.зависимости-DartifactId=kuku-jackson-core-Dversion=2.6.4-Dpackaging=jar

МВН установки:Установка-файл -единственный способ иметь установленный=с:\мои-банки\Куку-Джексон-привязку-2.6.4.jar-DgroupId=io.кюкю.зависимости-DartifactId=kuku-jackson-аннотации-Dversion=2.6.4-Dpackaging=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>