【问题标题】:How to create maven uber jar which includes dependencies with scope provided如何创建包含提供范围的依赖项的 maven uber jar
【发布时间】:2017-01-01 03:43:48
【问题描述】:
<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 build 不应该包含它们。因为它们是由容器提供的。

【问题讨论】:

    标签: maven maven-2 maven-3 maven-assembly-plugin


    【解决方案1】:

    预定义的jar-with-dependencies 描述符将运行时所需的所有依赖项解压缩到生成的 JAR 的根目录中。如果要添加提供的依赖项,可以在其上构建并添加特定的&lt;dependencySet&gt;&lt;scope&gt;provided&lt;/scope&gt;

    <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 的位置。

    【讨论】:

      【解决方案2】:

      试试 Maven Shade 插件:

      您可以控制应该在 uber JAR 中包含/排除哪些项目依赖项。很多选择。

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

      【讨论】:

      • 提供的 Maven 依赖范围在构建和测试项目期间使用。它们也需要运行,但不应导出,因为依赖项将由运行时提供,例如 servlet 容器或应用程序服务器。所以它不是预期的提供范围。对吗??
      【解决方案3】:

      这是一篇旧帖子,但我认为这两个答案都不准确,也不是 100% 正确。

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

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

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

      [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
      

      你得到这个的原因是因为你用程序集插件构建了一个新的 JAR,但你的组装 JAR 的分类器没有指定。

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

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

      <appendAssemblyId>false</appendAssemblyId>
      

      程序集 ID 是您的 uber 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 插件配置:

      <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 是这样命名的:&lt;project-name&gt;-1.0-with-dependencies.jar

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

      【讨论】:

        【解决方案4】:

        尝试像这样添加一个 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>
        

        【讨论】:

        • 这将包括不需要的测试范围依赖项。
        • 是的,你没有说你想要包括什么范围 - 所以显然只需将“测试”更改为你需要的任何范围。
        • @Tunaki 您接受的答案与这个答案完全相同。
        • 我没有写这个问题:)。但是标题说 其中包括提供范围的依赖项,因此不存在测试。
        • 从字面上看,将“测试”一词更改为“提供”。相同的答案。
        【解决方案5】:

        我也在创建一个分发文件,我做了一些类似下面的事情 程序集.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>
        

        【讨论】:

          猜你喜欢
          • 2014-10-06
          • 2011-12-31
          • 1970-01-01
          • 1970-01-01
          • 2018-07-30
          • 2016-05-28
          • 2013-03-29
          • 1970-01-01
          • 2019-07-15
          相关资源
          最近更新 更多