资源转换器

只要没有重叠,将来自多个工件的类/资源聚合到一个 uber JAR 中是直接的。否则,需要某种逻辑来合并来自多个 JAR 的资源。这就是资源转换器发挥作用的地方。

org.apache.maven.plugins.shade.resource中的变形金刚
ApacheLicenseResourceTransformer 防止许可证重复
ApacheNoticeResourceTransformer 准备合并通知
附加变压器 向资源添加内容
ComponentsXmlResourceTransformer 聚合 Plexus components.xml
DontIncludeResourceTransformer 防止包含匹配资源
GroovyResourceTransformer 合并 Apache Groovy 扩展模块
包括资源转换器 从项目中添加文件
清单资源转换器 MANIFEST中设置条目
PluginXmlResourceTransformer 聚合 Mavens plugin.xml
ResourceBundleAppendingTransformer 合并资源包
服务资源转换器 在META-INF/services资源中重新定位类名并将它们合并。
XmlAppendingTransformer 将 XML 内容添加到 XML 资源
org.apache.maven.plugins.shade.resource.properties中的变形金刚(从 3.2.2 开始可用)
属性变压器 合并拥有序号的属性文件以解决冲突
OpenWebBeansPropertiesTransformer 合并 Apache OpenWebBeans 配置文件
MicroprofileConfigTransformer 基于序数合并冲突的 Microprofile Config 属性

将 Plexus 组件描述符与ComponentsXmlResourceTransformer合并

针对 Plexus IoC 容器的组件的 JAR 包含一个META-INF/plexus/components.xml条目,用于声明组件及其要求。如果 uber JAR 聚合了多个 Plexus 组件,则需要使用ComponentsXmlResourceTransformer来合并 XML 描述符:

<project>
  ...
  <build>
    <plugins>
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-shade-plugin</artifactId>
        <version>3.2.4</version>
        <executions>
          <execution>
            <goals>
              <goal>shade</goal>
            </goals>
            <configuration>
              <transformers>
                <transformer implementation="org.apache.maven.plugins.shade.resource.ComponentsXmlResourceTransformer"/>
              </transformers>
            </configuration>
          </execution>
        </executions>
      </plugin>
    </plugins>
  </build>
  ...
</project>

从插件版本 1.3 开始,此资源转换器还将更新描述符以说明组件接口/实现(如果有)的重定位。

使用PluginXmlResourceTransformer 重定位 Maven 插件描述符的类

Plugin Tools 3.0引入了注解。现在对类的引用不再是类名作为字符串,而是实际的类引用。当您想重新定位类时,您必须手动维护META-INF/maven/plugin.xml,但现在可以使用PluginXmlResourceTransformer

<project>
  ...
  <build>
    <plugins>
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-shade-plugin</artifactId>
        <version>3.2.4</version>
        <executions>
          <execution>
            <goals>
              <goal>shade</goal>
            </goals>
            <configuration>
              <transformers>
                <transformer implementation="org.apache.maven.plugins.shade.resource.PluginXmlResourceTransformer"/>
              </transformers>
            </configuration>
          </execution>
        </executions>
      </plugin>
    </plugins>
  </build>
  ...
</project>

使用ServicesResourceTransformer连接服务条目

提供某些接口实现的 JAR 文件通常附带一个META-INF/services/目录,该目录将接口映射到它们的实现类以供服务定位器查找。要重定位这些实现类的类名,并将同一接口的多个实现合并到一个服务条目中,可以使用ServicesResourceTransformer :

<project>
  ...
  <build>
    <plugins>
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-shade-plugin</artifactId>
        <version>3.2.4</version>
        <executions>
          <execution>
            <goals>
              <goal>shade</goal>
            </goals>
            <configuration>
              <transformers>
                <transformer implementation="org.apache.maven.plugins.shade.resource.ServicesResourceTransformer"/>
              </transformers>
            </configuration>
          </execution>
        </executions>
      </plugin>
    </plugins>
  </build>
  ...
</project>

将特定文件的内容与AppendingTransformer、 XmlAppendingTransformer 和 ResourceBundleAppendingTransformer合并

一些 jar 包含具有相同文件名的其他资源(例如属性文件)。为避免覆盖,您可以选择通过将其内容附加到一个文件中来合并它们。一个很好的例子是在聚合 spring-context 和 plexus-spring jar 时。它们都有META-INF/spring.handlers文件,Spring 使用该文件来处理 XML 模式命名空间。您可以使用AppendingTransformer合并具有该特定名称的所有文件的内容,如下所示:

<project>
  ...
  <build>
    <plugins>
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-shade-plugin</artifactId>
        <version>3.2.4</version>
        <executions>
          <execution>
            <goals>
              <goal>shade</goal>
            </goals>
            <configuration>
              <transformers>
                <transformer implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
                  <resource>META-INF/spring.handlers</resource>
                </transformer>
                <transformer implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
                  <resource>META-INF/spring.schemas</resource>
                </transformer>
              </transformers>
            </configuration>
          </execution>
        </executions>
      </plugin>
    </plugins>
  </build>
  ...
</project>

对于 XML 文件,您可以改用XmlAppendingTransformer

<project>
  ...
  <build>
    <plugins>
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-shade-plugin</artifactId>
        <version>3.2.4</version>
        <executions>
          <execution>
            <goals>
              <goal>shade</goal>
            </goals>
            <configuration>
              <transformers>
                <transformer implementation="org.apache.maven.plugins.shade.resource.XmlAppendingTransformer">
                  <resource>META-INF/magic.xml</resource>
                  <!-- Add this to enable loading of DTDs
                  <ignoreDtd>false</ignoreDtd>
                  -->
                </transformer>
              </transformers>
            </configuration>
          </execution>
        </executions>
      </plugin>
    </plugins>
  </build>
  ...
</project>

从插件版本 1.3.1 开始,XmlAppendingTransformer默认不加载 DTD,从而避免网络访问。这种模式的潜在缺点是无法解析外部实体,这可能会导致转换失败,例如在使用某些 JRE 1.4 中使用的 Crimson XML 解析器时。如果转换后的资源使用外部实体,则可以重新打开 DTD 解析,或者将对xerces:xercesImpl:2.9.1的插件依赖添加到 POM。

对于 ResourceBundles 属性文件,您可以使用ResourceBundleAppendingTransformer代替,这也将尊重所有可用的语言环境:

<project>
  ...
  <build>
    <plugins>
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-shade-plugin</artifactId>
        <version>3.2.4</version>
        <executions>
          <execution>
            <goals>
              <goal>shade</goal>
            </goals>
            <configuration>
              <transformers>
                <transformer implementation="org.apache.maven.plugins.shade.resource.ResourceBundleAppendingTransformer">
                  <!-- the base name of the resource bundle, a fully qualified class name -->
                  <basename>path/to/Messages</basename>
                </transformer>
              </transformers>
            </configuration>
          </execution>
        </executions>
      </plugin>
    </plugins>
  </build>
  ...
</project>

使用DontIncludeResourceTransformer排除资源

DontIncludeResourceTransformer允许在资源名称以给定值结尾时排除资源。

例如,以下示例排除了以.txt结尾的所有资源。

<project>
  ...
  <build>
    <plugins>
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-shade-plugin</artifactId>
        <version>3.2.4</version>
        <executions>
          <execution>
            <goals>
              <goal>shade</goal>
            </goals>
            <configuration>
              <transformers>
                <transformer implementation="org.apache.maven.plugins.shade.resource.DontIncludeResourceTransformer">
                    <resource>.txt</resource>
                </transformer>
              </transformers>
            </configuration>
          </execution>
        </executions>
      </plugin>
    </plugins>
  </build>
  ...
</project>

由于 maven-shade-plugin-3.0 还可以提供不应包含的资源列表,例如:

<transformer implementation="org.apache.maven.plugins.shade.resource.DontIncludeResourceTransformer">
  <resources>
    <resource>.txt</resource>
    <resource>READ.me</resource>
  </resources>
</transformer>

使用IncludeResourceTransformer添加新资源

IncludeResourceTransformer允许项目文件以给定名称包含在包中。

例如,以下示例在META-INF目录中将README.txt作为README包含在包中。

<project>
  ...
  <build>
    <plugins>
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-shade-plugin</artifactId>
        <version>3.2.4</version>
        <executions>
          <execution>
            <goals>
              <goal>shade</goal>
            </goals>
            <configuration>
              <transformers>
                <transformer implementation="org.apache.maven.plugins.shade.resource.IncludeResourceTransformer">
                    <resource>META-INF/README</resource>
                    <file>README.txt</file>
                </transformer>
              </transformers>
            </configuration>
          </execution>
        </executions>
      </plugin>
    </plugins>
  </build>
  ...
</project>

使用ManifestResourceTransformer设置清单条目

ManifestResourceTransformer允许替换MANIFEST中的现有条目并添加新条目。

例如以下样本集

  • app.main.class属性值的Main-Class条目,
  • maven.compile.source属性值的X-Compile-Source-JDK条目和
  • maven.compile.target属性值的X-Compile-Target-JDK条目。

默认情况下,ManifestResourceTransformer将重新定位以下属性:

  • 出口包装
  • 进口包装
  • 提供能力
  • 需求能力

使用附加属性,您也可以指定需要重定位的属性。

<project>
  ...
  <build>
    <plugins>
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-shade-plugin</artifactId>
        <version>3.2.4</version>
        <executions>
          <execution>
            <goals>
              <goal>shade</goal>
            </goals>
            <configuration>
              <transformers>
                <transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
                  <manifestEntries>
                    <Main-Class>${app.main.class}</Main-Class>
                    <X-Compile-Source-JDK>${maven.compile.source}</X-Compile-Source-JDK>
                    <X-Compile-Target-JDK>${maven.compile.target}</X-Compile-Target-JDK>
                  </manifestEntries>
                </transformer>
              </transformers>
            </configuration>
          </execution>
        </executions>
      </plugin>
    </plugins>
  </build>
  ...
</project>

许可

使用ApacheLicenseResourceTransformer防止许可证重复

一些开源生产者(包括Apache 软件基金会)在 META-INF 目录中包含了他们的许可证副本。这些通常被命名为LICENSELICENSE.txt。在合并这些依赖项时,添加这些资源可能会造成混乱。ApacheLicenseResourceTransformer确保不会合并重复的许可证(根据此约定命名)

例如,以下内容可防止将commons-collections依赖项中的许可证合并到

<project>
  ...
  <build>
    <plugins>
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-shade-plugin</artifactId>
        <version>3.2.4</version>
        <executions>
          <execution>
            <goals>
              <goal>shade</goal>
            </goals>
            <configuration>
              <transformers>
                <transformer implementation="org.apache.maven.plugins.shade.resource.ApacheLicenseResourceTransformer">
                </transformer>
              </transformers>
            </configuration>
          </execution>
        </executions>
      </plugin>
    </plugins>
  </build>
  ...
</project>

使用ApacheNoticeResourceTransformer聚合通知

某些许可证(包括Apache 许可证,第 2 版)要求通知由下游分销商保留。ApacheNoticeResourceTransformer自动组装适当的NOTICE

例如,简单地合并依赖通知:

<project>
  ...
  <build>
    <plugins>
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-shade-plugin</artifactId>
        <version>3.2.4</version>
        <executions>
          <execution>
            <goals>
              <goal>shade</goal>
            </goals>
            <configuration>
              <transformers>
                <transformer implementation="org.apache.maven.plugins.shade.resource.ApacheNoticeResourceTransformer">
                    <addHeader>false</addHeader>
                </transformer>
              </transformers>
            </configuration>
          </execution>
        </executions>
      </plugin>
    </plugins>
  </build>
  ...
</project>

使用GroovyResourceTransformer聚合 Apache Groovy 扩展模块描述符

Apache Groovy 语言提供位于META-INF/services/org.codehaus.groovy.runtime.ExtensionModule 的扩展模块,这些模块使用属性文件格式。GroovyResourceTransformer自动组装 Groovy 扩展模块NOTICE

比如简单合并几个jar的扩展模块:

<project>
  ...
  <build>
    <plugins>
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-shade-plugin</artifactId>
        <version>3.2.4</version>
        <executions>
          <execution>
            <goals>
              <goal>shade</goal>
            </goals>
            <configuration>
              <transformers>
                <transformer implementation="org.apache.maven.plugins.shade.resource.GroovyResourceTransformer">
                  <extModuleName>the-aggregated-module</extModuleName>
                  <extModuleVersion>1.0.0</extModuleVersion>
                </transformer>
              </transformers>
            </configuration>
          </execution>
        </executions>
      </plugin>
    </plugins>
  </build>
 ...
</project>

使用PropertiesTransformer合并属性文件

PropertiesTransformer允许合并一组属性文件,并根据给定每个文件优先级的序数来解决冲突。可选的alreadyMergedKey允许在文件中具有布尔标志,如果设置为 true,则请求将文件用作合并的结果。如果两个文件在合并过程中被认为是完整的,那么阴影将失败。

<project>
  ...
  <build>
    <plugins>
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-shade-plugin</artifactId>
        <version>3.2.4</version>
        <executions>
          <execution>
            <goals>
              <goal>shade</goal>
            </goals>
            <configuration>
              <transformers>
                <transformer implementation="org.apache.maven.plugins.shade.resource.properties.PropertiesTransformer">
                  <!-- required configuration -->
                  <resource>configuration/application.properties</resource>
                  <ordinalKey>ordinal</ordinalKey>
                  <!-- optional configuration -->
                  <alreadyMergedKey>already_merged</alreadyMergedKey>
                  <defaultOrdinal>0</defaultOrdinal>
                  <reverseOrder>false</reverseOrder>
                </transformer>
              </transformers>
            </configuration>
          </execution>
        </executions>
      </plugin>
    </plugins>
  </build>
  ...
</project>

将 Apache OpenWebBeans 配置与OpenWebBeansPropertiesTransformer合并

OpenWebBeansPropertiesTransformer为 Apache OpenWebBeans 配置文件预配置一个PropertiesTransformer 。

<project>
  ...
  <build>
    <plugins>
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-shade-plugin</artifactId>
        <version>3.2.4</version>
        <executions>
          <execution>
            <goals>
              <goal>shade</goal>
            </goals>
            <configuration>
              <transformers>
                <transformer implementation="org.apache.maven.plugins.shade.resource.properties.OpenWebBeansPropertiesTransformer" />
              </transformers>
            </configuration>
          </execution>
        </executions>
      </plugin>
    </plugins>
  </build>
  ...
</project>

将 Microprofile Config 属性与MicroprofileConfigTransformer合并

MicroprofileConfigTransformer为 Microprofile Config预配置一个PropertiesTransformer。唯一需要的配置是序数。支持 alreadyMergedKey但规范未定义。

<project>
  ...
  <build>
    <plugins>
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-shade-plugin</artifactId>
        <version>3.2.4</version>
        <executions>
          <execution>
            <goals>
              <goal>shade</goal>
            </goals>
            <configuration>
              <transformers>
                <transformer implementation="org.apache.maven.plugins.shade.resource.properties.MicroprofileConfigTransformer">
                  <resource>configuration/app.properties</resource>
                </transformer>
              </transformers>
            </configuration>
          </execution>
        </executions>
      </plugin>
    </plugins>
  </build>
  ...
</project>