我想将我的项目打包在一个可执行的JAR中进行分发。

如何使Maven项目将所有依赖JAR打包到输出JAR中?


当前回答

您可以使用依赖插件在包阶段之前在单独的目录中生成所有依赖项,然后将其包含在清单的类路径中:

<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-dependency-plugin</artifactId>
    <executions>
        <execution>
            <id>copy-dependencies</id>
            <phase>prepare-package</phase>
            <goals>
                <goal>copy-dependencies</goal>
            </goals>
            <configuration>
                <outputDirectory>${project.build.directory}/lib</outputDirectory>
                <overWriteReleases>false</overWriteReleases>
                <overWriteSnapshots>false</overWriteSnapshots>
                <overWriteIfNewer>true</overWriteIfNewer>
            </configuration>
        </execution>
    </executions>
</plugin>
<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-jar-plugin</artifactId>
    <configuration>
        <archive>
            <manifest>
                <addClasspath>true</addClasspath>
                <classpathPrefix>lib/</classpathPrefix>
                <mainClass>theMainClass</mainClass>
            </manifest>
        </archive>
    </configuration>
</plugin>

或者,使用${project.build.directory}/classes/lib作为OutputDirectory将所有JAR文件集成到主JAR文件中,但随后需要添加自定义类加载代码来加载JAR文件。

其他回答

<build>
  <plugins>
    <plugin>
      <artifactId>maven-assembly-plugin</artifactId>
      <configuration>
        <archive>
          <manifest>
            <mainClass>fully.qualified.MainClass</mainClass>
          </manifest>
        </archive>
        <descriptorRefs>
          <descriptorRef>jar-with-dependencies</descriptorRef>
        </descriptorRefs>
      </configuration>
    </plugin>
  </plugins>
</build>

你用

mvn clean compile assembly:single

编译目标应在组装之前添加:单个或其他项目的代码不包含在内。

请在评论中查看更多详细信息。


通常,此目标与自动执行的构建阶段相关联。这确保在执行mvn安装或执行部署/发布时构建JAR。

<build>
  <plugins>
    <plugin>
      <artifactId>maven-assembly-plugin</artifactId>
      <configuration>
        <archive>
          <manifest>
            <mainClass>fully.qualified.MainClass</mainClass>
          </manifest>
        </archive>
        <descriptorRefs>
          <descriptorRef>jar-with-dependencies</descriptorRef>
        </descriptorRefs>
      </configuration>
      <executions>
        <execution>
          <id>make-assembly</id> <!-- this is used for inheritance merges -->
          <phase>package</phase> <!-- bind to the packaging phase -->
          <goals>
            <goal>single</goal>
          </goals>
        </execution>
      </executions>
    </plugin>
  </plugins>
</build>

如果您真的想重新打包单个结果JAR中的其他JAR内容,另一个选项是Maven Assembly插件。它通过<unpack>true</unpack>解包,然后将所有内容重新打包到一个目录中。然后,您将有第二个过程,将其构建到一个大型JAR中。

另一个选项是OneJar插件。这将在一个步骤中执行上述重新打包操作。

使用maven shade插件将所有依赖项打包到一个über JAR文件中。它还可以通过指定主类来构建可执行JAR文件。在尝试使用maven汇编和maven jar之后,我发现这个插件最适合我的需求。

我发现这个插件特别有用,因为它合并了特定文件的内容,而不是覆盖它们。当JAR文件中存在同名的资源文件并且插件试图打包所有资源文件时,这是需要的。

请参见以下示例:

<plugins>
    <!-- This plugin provides the capability to package
         the artifact in an über-JAR file, including
         its dependencies and to shade - i.e. rename -
         the packages of some of the dependencies. -->
    <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-shade-plugin</artifactId>
        <version>1.4</version>
        <executions>
            <execution>
                <phase>package</phase>
                <goals>
                    <goal>shade</goal>
                </goals>
                <configuration>
                    <artifactSet>
                        <!-- Signed JAR files-->
                        <excludes>
                            <exclude>bouncycastle:bcprov-jdk15</exclude>
                        </excludes>
                    </artifactSet>

                    <transformers>
                        <transformer
                            implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
                            <!-- Main class -->
                            <mainClass>com.main.MyMainClass</mainClass>
                        </transformer>

                        <!-- Use resource transformers to prevent file overwrites -->
                        <transformer
                            implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
                            <resource>properties.properties</resource>
                        </transformer>
                        <transformer
                            implementation="org.apache.maven.plugins.shade.resource.XmlAppendingTransformer">
                            <resource>applicationContext.xml</resource>
                        </transformer>
                        <transformer
                            implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
                            <resource>META-INF/cxf/cxf.extension</resource>
                        </transformer>
                        <transformer
                            implementation="org.apache.maven.plugins.shade.resource.XmlAppendingTransformer">
                            <resource>META-INF/cxf/bus-extensions.xml</resource>
                        </transformer>
                    </transformers>
                </configuration>
            </execution>
        </executions>
    </plugin>
</plugins>

您可以使用依赖插件在包阶段之前在单独的目录中生成所有依赖项,然后将其包含在清单的类路径中:

<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-dependency-plugin</artifactId>
    <executions>
        <execution>
            <id>copy-dependencies</id>
            <phase>prepare-package</phase>
            <goals>
                <goal>copy-dependencies</goal>
            </goals>
            <configuration>
                <outputDirectory>${project.build.directory}/lib</outputDirectory>
                <overWriteReleases>false</overWriteReleases>
                <overWriteSnapshots>false</overWriteSnapshots>
                <overWriteIfNewer>true</overWriteIfNewer>
            </configuration>
        </execution>
    </executions>
</plugin>
<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-jar-plugin</artifactId>
    <configuration>
        <archive>
            <manifest>
                <addClasspath>true</addClasspath>
                <classpathPrefix>lib/</classpathPrefix>
                <mainClass>theMainClass</mainClass>
            </manifest>
        </archive>
    </configuration>
</plugin>

或者,使用${project.build.directory}/classes/lib作为OutputDirectory将所有JAR文件集成到主JAR文件中,但随后需要添加自定义类加载代码来加载JAR文件。

使用maven-assembly-plugin-2.2.1查找共享程序集文件有什么问题?

尝试使用descriptorId配置参数,而不是描述符/描述符或descriptorRefs/descriptorRef参数。

它们都不做您需要的事情:在类路径上查找文件。当然,您需要在maven程序集插件的类路径中添加共享程序集所在的包(见下文)。如果您使用的是Maven 2.x(而不是Maven 3.x),则可能需要在pluginManagement部分的最顶层父pom.xml中添加此依赖项。

有关详细信息,请参见此。

类:org.apache.maven.plugin.assembly.io.DefaultAssemblyReader

例子:

<!-- Use the assembly plugin to create a zip file of all our dependencies. -->
<plugin>
    <artifactId>maven-assembly-plugin</artifactId>
    <version>2.2.1</version>
    <executions>
        <execution>
            <id>make-assembly</id>
            <phase>package</phase>
            <goals>
                <goal>single</goal>
            </goals>
            <configuration>
                <descriptorId>assembly-zip-for-wid</descriptorId>
            </configuration>
        </execution>
    </executions>
    <dependencies>
        <dependency>
            <groupId>cz.ness.ct.ip.assemblies</groupId>
            <artifactId>TEST_SharedAssemblyDescriptor</artifactId>
            <version>1.0.0-SNAPSHOT</version>
        </dependency>
    </dependencies>
</plugin>