资源转换器

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

合并 Plexus 组件描述符

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

连接服务条目

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

<project>
  ...
  <build>
    <plugins>
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-shade-plugin</artifactId>
        <version>1.3.3</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>

合并特定文件的内容

一些 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.3.3</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.3.3</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。