资源转换器

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

org.apache.maven.plugins.shade.resource中的变形金刚
ApacheLicenseResourceTransformer防止许可证重复
ApacheNoticeResourceTransformer准备合并通知
附加变压器向资源添加内容
ComponentsXmlResourceTransformer聚合 Plexus components.xml
DontIncludeResourceTransformer防止包含匹配资源
包括资源转换器从项目中添加文件
清单资源转换器MANIFEST中设置条目
服务资源转换器合并META-INF/服务资源
XmlAppendingTransformer将 XML 内容添加到 XML 资源

将 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>1.5</version>
        <executions>
          <execution>
            <phase>package</phase>
            <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 开始,此资源转换器还将更新描述符以说明组件接口/实现(如果有)的重定位。

使用ServicesResourceTransformer连接服务条目

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

<project>
  ...
  <build>
    <plugins>
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-shade-plugin</artifactId>
        <version>1.5</version>
        <executions>
          <execution>
            <phase>package</phase>
            <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合并特定文件的内容

一些 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>1.5</version>
        <executions>
          <execution>
            <phase>package</phase>
            <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>1.5</version>
        <executions>
          <execution>
            <phase>package</phase>
            <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。

使用DontIncludeResourceTransformer排除资源

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

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

<project>
  ...
  <build>
    <plugins>
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-shade-plugin</artifactId>
        <version>1.5</version>
        <executions>
          <execution>
            <phase>package</phase>
            <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>

使用IncludeResourceTransformer添加新资源

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

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

<project>
  ...
  <build>
    <plugins>
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-shade-plugin</artifactId>
        <version>1.5</version>
        <executions>
          <execution>
            <phase>package</phase>
            <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条目。
    <project>
      ...
      <build>
        <plugins>
          <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-shade-plugin</artifactId>
            <version>1.5</version>
            <executions>
              <execution>
                <phase>package</phase>
                <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>1.5</version>
        <executions>
          <execution>
            <phase>package</phase>
            <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>1.5</version>
        <executions>
          <execution>
            <phase>package</phase>
            <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>