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

时间:2016-08-24 20:58:06

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

<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不应该包含它们。因为那些是由容器提供的。

5 个答案:

答案 0 :(得分:2)

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

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

答案 1 :(得分:0)

尝试添加如下的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>

答案 2 :(得分:0)

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

答案 3 :(得分:0)

尝试使用Maven Shade插件:

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

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

答案 4 :(得分:0)

这是一个过时的帖子,但我认为这两个答案都不正确,也不是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

之所以会这样,是因为您使用了assembly-plugin构建了一个新的JAR,但未指定组装后的JAR的分类器。

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

并且您使用Assembly插件构建的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>
    <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

希望它可以帮助您构建完美的超级JAR。