如何创建 Maven uber jar,其中包含提供范围的依赖项

How to create maven uber jar which includes dependencies with scope provided

<plugin>
    <artifactId>maven-assembly-plugin</artifactId>
    <executions>
      <execution>
        <phase>package</phase>
        <goals>
          <goal>single</goal>
        </goals>
      </execution>
    </executions>
    <configuration>
         <archive>
            <manifest>           
                <mainClass>com.XXXX.XXXXOfflineApp</mainClass>
            </manifest>
        </archive>
      <descriptorRefs>
        <descriptorRef>jar-with-dependencies</descriptorRef>
      </descriptorRefs>
    </configuration>
  </plugin>
</plugins>

我有上面的代码片段来创建一个带有依赖项的 jar,但是在我的 pom 中我也有一些提供范围的依赖项但是这些不包含在 uber jar 中,我无法更改这些依赖项的范围,因为常规 jars 构建不应包含容器提供的 them.Since。

尝试像这样添加 assembly.xml 文件:

<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>fat-tests</id>
    <formats>
        <format>jar</format>
    </formats>
    <includeBaseDirectory>false</includeBaseDirectory>
    <dependencySets>
        <dependencySet>
            <outputDirectory>/</outputDirectory>
            <useProjectArtifact>true</useProjectArtifact>
            <unpack>true</unpack>
            <scope>test</scope>
        </dependencySet>
    </dependencySets>
    <fileSets>
        <fileSet>
            <directory>${project.build.directory}/test-classes</directory>
            <outputDirectory>/</outputDirectory>
            <includes>
                <include>**/*.class</include>
            </includes>
            <useDefaultExcludes>true</useDefaultExcludes>
        </fileSet>
    </fileSets>
</assembly>

为每个范围添加您需要的任何依赖集。

您的 pom.xml

中也需要这个
    <plugin>
        <artifactId>maven-assembly-plugin</artifactId>
        <configuration>
            <descriptor>src/main/assembly/assembly.xml</descriptor>
        </configuration>

预定义的jar-with-dependencies descriptor unpacks all dependencies needed at runtime into the root of the produced JAR. If you want to add provided dependencies, it is possible to build on it and add a specific <dependencySet><scope>provided</scope>

<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>jar-with-dependencies</id>
  <formats>
    <format>jar</format>
  </formats>
  <includeBaseDirectory>false</includeBaseDirectory>
  <dependencySets>
    <dependencySet>
      <outputDirectory>/</outputDirectory>
      <useProjectArtifact>true</useProjectArtifact>
      <unpack>true</unpack>
      <scope>provided</scope>
    </dependencySet>
    <dependencySet>
      <outputDirectory>/</outputDirectory>
      <useProjectArtifact>true</useProjectArtifact>
      <unpack>true</unpack>
      <scope>runtime</scope>
    </dependencySet>
  </dependencySets>
</assembly>

这将包括运行时通常需要的所有依赖项(因此具有 compileruntime 的范围)以及具有 provided 范围的所有依赖项。

您将配置此描述符格式的使用:

<plugin>
  <artifactId>maven-assembly-plugin</artifactId>
  <version>2.6</version>
  <executions>
    <execution>
      <id>id</id>
      <phase>package</phase>
      <goals>
        <goal>single</goal>
      </goals>
      <configuration>
        <archive>
          <manifest>
            <mainClass>com.XXXX.XXXXOfflineApp</mainClass>
          </manifest>
        </archive>
        <descriptors>
          <descriptor>path/to/assembly.xml</descriptor>
        </descriptors>
      </configuration>
    </execution>
  </executions>
</plugin>

其中 path/to/assembly.xml 对应于上述描述符格式的路径,相对于 POM 的位置。

我也在努力创建一个分发文件,我做了如下的一些事情 assembly.xml

<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>jar-with-dependencies</id>
    <formats>
        <format>jar</format>
    </formats>
    <includeBaseDirectory>false</includeBaseDirectory>
    <dependencySets>
        <dependencySet>
            <outputDirectory>/</outputDirectory>
            <useProjectArtifact>true</useProjectArtifact>
            <unpack>true</unpack>
            <scope>provided</scope>
        </dependencySet>
        <dependencySet>
            <outputDirectory>/</outputDirectory>
            <useProjectArtifact>true</useProjectArtifact>
            <unpack>true</unpack>
            <scope>runtime</scope>
        </dependencySet>
    </dependencySets>
</assembly>

distribution.xml

   <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">
    </assembly>
    <id>offline-distribution</id>
    <!-- Specifies that our binary distribution is a zip package -->
    <formats>
        <format>zip</format>
    </formats>
    <!-- Adds the dependencies of our application to the lib directory -->
    <dependencySets>

        <dependencySet>
            <useProjectArtifact>true</useProjectArtifact>
            <outputDirectory>/lib</outputDirectory>
            <unpack>false</unpack>
        </dependencySet>
        <dependencySet>
            <outputDirectory>/lib</outputDirectory>
            <useProjectArtifact>true</useProjectArtifact>
            <unpack>false</unpack>
            <scope>provided</scope>
        </dependencySet>
        <dependencySet>
            <outputDirectory>/lib</outputDirectory>
            <useProjectArtifact>true</useProjectArtifact>
            <unpack>false</unpack>
            <scope>runtime</scope>
        </dependencySet>
    </dependencySets>

    <fileSets>

        <fileSet>
            <directory>${project.basedir}</directory>
            <outputDirectory>/bin</outputDirectory>
            <includes>
                <include>startup*</include>
            </includes>
            <useDefaultExcludes>true</useDefaultExcludes>
        </fileSet>
        <fileSet>
            <directory>${project.basedir}</directory>
            <outputDirectory>/</outputDirectory>
            <includes>
                <include>README*</include>
            </includes>
            <useDefaultExcludes>true</useDefaultExcludes>
        </fileSet>
        <fileSet>
            <directory>${project.basedir}/src/main/resources</directory>
            <outputDirectory>/config</outputDirectory>
            <includes>
                <include>log4j2.xml</include>
            </includes>
            <useDefaultExcludes>true</useDefaultExcludes>
        </fileSet>
    </fileSets>
</assembly>

父pom.xml

<plugin>
            <artifactId>maven-assembly-plugin</artifactId>
            <version>2.6</version>
            <executions>
                <execution>
                    <id>id</id>
                    <phase>package</phase>
                    <goals>
                        <goal>single</goal>
                    </goals>
                    <configuration>
                        <!-- <archive>
                            <manifest>
                                <mainClass>com.XXXX.XXXXOfflineApp</mainClass>
                            </manifest>
                        </archive> -->
                        <descriptors>
                            <descriptor>distribution.xml</descriptor>
                             <descriptor>assembly.xml</descriptor>
                        </descriptors>
                    </configuration>
                </execution>
            </executions>
        </plugin>

试用 Maven Shade 插件:

您可以控制在 uber JAR 中应该 included/excluded 哪些项目依赖项。很多选择。

https://maven.apache.org/plugins/maven-shade-plugin/examples/includes-excludes.html

这是一个旧的 post 但我认为这两个答案都不准确而且不是 100% 正确。

事实上,uber JAR 必须包含所有运行时和提供的依赖项。但第一期从这里开始。

通常,依赖项包含它们自己的 MANIFEST.MF 文件,如果您使用上面的示例将它们组装到 JAR 中,那么您将在 Maven 构建期间得到一个 WARNING 关于您覆盖它们的事实因为 JAR 只能有一个 MANIFEST 文件。这个不好。所以请不要把依赖放在同一个目录下。

第二个问题与以下两个警告有关:

[WARNING] Configuration options: 'appendAssemblyId' is set to false, and 'classifier' is missing. Instead of attaching the assembly file: [...]/target/....jar, it will become the file for main project artifact.

NOTE: If multiple descriptors or descriptor-formats are provided for this project, the value of this file will be non-deterministic!

[WARNING] Replacing pre-existing project main-artifact file: [...]/target/....jar with assembly file: [...]/target/....jar

你得到这个的原因是你用 assembly-plugin 构建了一个新的 JAR,但是没有指定你组装的 JAR 的分类器。

非 pom 类型的 Maven 项目默认生成为主工件。这个工件是 maven 打包(JAR,WAR,或 EAR)的结果。此工件附加到您的项目并由 Maven 在使用 mvn installmvn deploy 安装、部署或发布您的项目时使用。当然你可以在target文件夹下生成不同的文件,但是你的主神器还是一样的

并且您使用程序集插件构建的 JAR 与您的默认工件冲突。所以我强烈建议你不要使用这个:

<appendAssemblyId>false</appendAssemblyId>

程序集 ID 是您的超级 JAR 的分类,因此请将上面的 属性 设置为 TRUE 或完全忽略它,因为它的默认值为 TRUE。

工件的默认命名约定是这样的:artifactId-version(-classifier).type

您可以在下面找到完整的示例。

pom.xml:

<build>
    <plugins>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-assembly-plugin</artifactId>
            <version>${maven.assembly.plugin.version}</version>
            <configuration>
                <appendAssemblyId>false</appendAssemblyId>
                <finalName>${project.artifactId}-aa-${project.version}</finalName>
                <descriptors>
                    <descriptor>${basedir}/src/main/resources/assembly.xml</descriptor>
                </descriptors>
                <archive>
                    <manifest>
                        <mainClass>x.y.z.Main</mainClass>
                    </manifest>
                </archive>
            </configuration>
            <executions>
                <execution>
                    <phase>package</phase>
                    <goals>
                        <goal>single</goal>
                    </goals>
                </execution>
            </executions>
        </plugin>
    </plugins>
</build>

程序集插件配置:

<assembly>
    <id>with-dependencies</id>
    <formats>
        <format>jar</format>
    </formats>
    <includeBaseDirectory>false</includeBaseDirectory>
    <dependencySets>
        <dependencySet>
            <outputDirectory>/</outputDirectory>
            <useProjectArtifact>true</useProjectArtifact>
            <unpack>true</unpack>
            <scope>provided</scope>
        </dependencySet>
        <dependencySet>
            <outputDirectory>/</outputDirectory>
            <useProjectArtifact>true</useProjectArtifact>
            <unpack>true</unpack>
            <scope>runtime</scope>
        </dependencySet>
    </dependencySets>
</assembly>

组装好的 JAR 是这样命名的:<project-name>-1.0-with-dependencies.jar

希望它能帮助您构建完美的 uber JAR。