Maven 构建 jar:合并来自依赖项的重复资源

Maven building jar: merge duplicate resources from dependencies

我遇到了这个问题:

我有一个带有 spring-boot 的项目。它在eclipse上完美运行,但我需要生成一个带有依赖项的jar,所以我在pom中添加了maven-assembly-plugin配置。

一些 spring 依赖项在 META-INF 中有一个名为 spring.schemas 的文件,我需要将所有 spring.schemas 合并为一个(spring-上下文,spring-豆等)

我尝试 this solution 使用 maven-shade-pluggin 和 AppendingTransformer,它完美地合并了所有 spring.schemas...但是它有一个问题,当我执行 jar 时,它失败了:

java.lang.IllegalStateException: Unable to open nested entry 'lib/spring-boot-starter-batch-1.2.4.RELEASE.jar'. 
It has been compressed and nested jar files must be stored without compression.
Please check the mechanism used to create your executable jar file

所以,shade插件压缩jar,spring-boot不喜欢,没办法关闭shade中的压缩。我手动复制由 shade 生成的 shade spring.schemas 并将其放入具有依赖项的 maven-assembly-pluggin 生成和未压缩的 jar 中。有效。

然后我尝试将生成的 spring.schemas 包含到我的资源文件夹中,但它总是被 spring-context 中的 spring.schemas 覆盖。

我还尝试 this other solution 在程序集中使用描述符 XML 从依赖 jar 中排除 spring.schemas,但它不起作用:

<assembly
    xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.3"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.3 http://maven.apache.org/xsd/assembly-1.1.3.xsd">
    <id>distribution</id>
    <formats>
        <format>jar</format>
    </formats>
    <dependencySets>
        <dependencySet>
            <outputDirectory>/</outputDirectory>
            <includes>
                <include>org.springframework:spring-context</include>
            </includes>
            <unpack>true</unpack>
            <unpackOptions>
                <excludes>
                    <exclude>**/spring.schemas</exclude>
                </excludes>
            </unpackOptions>
        </dependencySet>
        <dependencySet>
            <outputDirectory>/</outputDirectory>
            <excludes>
                <exclude>org.springframework:spring-context</exclude>
            </excludes>
            <unpack>true</unpack>
        </dependencySet> 
    </dependencySets>
</assembly>
            <plugin>
                <artifactId>maven-assembly-plugin</artifactId>
                <configuration>
                    <descriptorRefs>
                        <descriptorRef>jar-with-dependencies</descriptorRef>
                    </descriptorRefs>
                    <archive>
                        <manifest>
                            <mainClass>org.springframework.batch.core.launch.support.CommandLineJobRunner</mainClass>
                        </manifest>
                        <compress>false</compress>
                    </archive>
                    <descriptors>
                        <descriptor>src/main/assembly/distribution.xml</descriptor>
                    </descriptors>
                </configuration>
                <executions>
                    <execution>
                        <id>make-assembly</id>
                        <phase>package</phase>
                        <goals>
                            <goal>single</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>

这是我的依赖项:

<dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-batch</artifactId>
        </dependency>
        <dependency>
            <groupId>org.hsqldb</groupId>
            <artifactId>hsqldb</artifactId>
        </dependency>
        <!-- MySql 5.5 Connector -->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.1.35</version>
        </dependency>
    </dependencies>

有什么想法吗?提前致谢

而不是使用 maven-assembly-plugin 和 maven-shade-pluggin,我会尝试使用 Spring Boot 自己的 spring-boot-maven-plugin 可以用来创建一个可执行的“胖”JAR。请参阅 this reference documentation page,“73.2 使用 Maven 创建可执行 JAR”部分。

<build>
<plugins>
    <plugin>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-maven-plugin</artifactId>
    </plugin>
</plugins>

或者,如果您不使用 spring-boot-starter-parent POM:

<build>
<plugins>
    <plugin>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-maven-plugin</artifactId>
        <version>1.2.5.RELEASE</version>
        <executions>
            <execution>
                <goals>
                    <goal>repackage</goal>
                </goals>
            </execution>
        </executions>
    </plugin>
</plugins>

您可以使用 maven-assembly-plugin.

将插件添加到您的 pom.xml:

<plugin>
  <groupId>org.apache.maven.plugins</groupId>
  <artifactId>maven-assembly-plugin</artifactId>
  <version>3.1.1</version>
  <executions>
    <execution>
      <id>make-assembly</id>
      <phase>package</phase>
      <goals>
        <goal>single</goal>
      </goals>
    </execution>
  </executions>
  <configuration>
    <descriptors>
      <descriptor>fat-jar.xml</descriptor>
    </descriptors>
  </configuration>
</plugin>

在您的 pom.xml 旁边添加一个 fat-jar.xml 描述符:

<assembly xmlns="http://maven.apache.org/ASSEMBLY/2.1.0"
          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
          xsi:schemaLocation="http://maven.apache.org/ASSEMBLY/2.1.0 http://maven.apache.org/xsd/assembly-2.1.0.xsd">
  <id>fat</id>
  <formats>
    <format>jar</format>
  </formats>
  <includeBaseDirectory>false</includeBaseDirectory>
  <dependencySets>
    <dependencySet>
      <outputDirectory>/</outputDirectory>
      <useProjectArtifact>true</useProjectArtifact>
      <unpack>true</unpack>
      <scope>runtime</scope>
    </dependencySet>
  </dependencySets>
  <containerDescriptorHandlers>
    <containerDescriptorHandler>
      <handlerName>metaInf-spring</handlerName>
    </containerDescriptorHandler>
  </containerDescriptorHandlers>
</assembly>

注意 metaInf-spring 处理程序。它将合并名称以 spring 单词开头的所有 META-INF 重复文件。

参考文档:https://maven.apache.org/plugins/maven-assembly-plugin/examples/single/using-container-descriptor-handlers.html