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

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


当前回答

我尝试了多种解决方案,但这是一种在我们想要创建一个不可执行的胖JAR文件的场景中非常有效的解决方案,该文件包含外部系统的所有内部依赖项,而这些依赖项与之前无关。测试了生产场景。

将其包含在pom.xml文件中:

<?xml version="1.0" encoding="UTF-8"?>
<build>
   <sourceDirectory>src</sourceDirectory>
   <plugins>
      <plugin>
         <artifactId>maven-compiler-plugin</artifactId>
         <version>3.8.1</version>
         <configuration>
            <source>1.8</source>
            <target>1.8</target>
         </configuration>
      </plugin>
      <plugin>
         <artifactId>maven-assembly-plugin</artifactId>
         <configuration>
            <descriptorRefs>
               <descriptorRef>jar-with-dependencies</descriptorRef>
            </descriptorRefs>
         </configuration>
      </plugin>
   </plugins>
</build>

要运行以构建胖JAR文件的命令:

mvn assembly:assembly

其他回答

为了解决这个问题,我们将使用Maven Assembly插件,该插件将JAR文件及其依赖JAR文件一起创建为单个可执行JAR文件。只需在pom.xml文件中添加以下插件配置。

<build>
   <pluginManagement>
      <plugins>
         <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-assembly-plugin</artifactId>
            <configuration>
               <archive>
                  <manifest>
                     <addClasspath>true</addClasspath>
                     <mainClass>com.your.package.MainClass</mainClass>
                  </manifest>
               </archive>
               <descriptorRefs>
                  <descriptorRef>jar-with-dependencies</descriptorRef>
               </descriptorRefs>
            </configuration>
            <executions>
               <execution>
                  <id>make-my-jar-with-dependencies</id>
                  <phase>package</phase>
                  <goals>
                     <goal>single</goal>
                  </goals>
               </execution>
            </executions>
         </plugin>
      </plugins>
   </pluginManagement>
</build>

完成此操作后,不要忘记使用以下命令运行Maven工具:

mvn clean compile assembly:single

Maven-将JAR文件及其依赖JAR文件一起创建为单个可执行JAR文件

这也是一种选择。您将能够构建JAR文件。

<build>
    <plugins>
        <plugin>
            <!-- Build an executable JAR -->
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-jar-plugin</artifactId>
            <version>2.4</version>
            <configuration>
                <archive>
                    <manifest>
                        <addClasspath>true</addClasspath>
                        <classpathPrefix>lib/</classpathPrefix>
                        <mainClass>WordListDriver</mainClass>
                    </manifest>
                </archive>
            </configuration>
        </plugin>
    </plugins>
</build>

这篇博客文章展示了结合maven jar和maven汇编插件的另一种方法。通过博客文章中的程序集配置XML文件,还可以控制依赖项是否将被扩展或仅被收集在文件夹中并由清单中的类路径条目引用:

理想的解决方案是将jar包含在lib文件夹中,主jar的manifest.mf文件包含类路径中的所有jar。

这里描述的正是这个:使用Maven的可执行JAR文件和从属JAR文件

对于任何想要从über JAR文件中排除特定依赖项的人来说,这是一个适合我的解决方案:

<project...>
    <dependencies>
        <dependency>
            <groupId>org.apache.spark</groupId>
            <artifactId>spark-core_2.11</artifactId>
            <version>1.6.1</version>
            <scope>provided</scope> <!--  <=============  -->
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <artifactId>maven-assembly-plugin</artifactId>
                <configuration>
                    <descriptorRefs>
                        <descriptorRef>jar-with-dependencies</descriptorRef>
                    </descriptorRefs>
                    <archive>
                        <manifest>
                            <mainClass>...</mainClass>
                        </manifest>
                    </archive>
                </configuration>
                <executions>
                    <execution>
                        <id>make-assembly</id>
                        <phase>package</phase>
                        <goals>
                            <goal>single</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>
</project>

它不是mvn程序集插件的配置,而是依赖项的属性。

我比较了本文中提到的树插件。我生成了两个JAR文件和一个包含所有JAR文件的目录。我比较了结果,肯定maven shade插件是最好的。

我的挑战是我有多个需要合并的Spring资源,以及jax-rs和JDBC服务。与maven汇编插件相比,它们都被shade插件正确合并。在这种情况下,除非您将它们复制到自己的资源文件夹中并手动合并一次,否则Spring将失败。

两个插件都输出正确的依赖树。我有多个作用域,如测试、提供、编译等。两个插件都跳过了测试和提供。他们都生成了相同的清单,但我能够使用他们的转换器使用shade插件合并许可证。使用maven依赖插件当然不会有这些问题,因为JAR文件没有被提取。但正如其他人所指出的,您需要携带一个额外的文件才能正常工作。

以下是pom.xml文件的片段:

<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>
                <includeScope>compile</includeScope>
                <excludeTransitive>true</excludeTransitive>
                <overWriteReleases>false</overWriteReleases>
                <overWriteSnapshots>false</overWriteSnapshots>
                <overWriteIfNewer>true</overWriteIfNewer>
            </configuration>
        </execution>
    </executions>
</plugin>

<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-assembly-plugin</artifactId>
    <version>2.6</version>
    <configuration>
        <archive>
            <manifest>
                <addClasspath>true</addClasspath>
                <mainClass>com.rbccm.itf.cdd.poller.landingzone.LandingZonePoller</mainClass>
            </manifest>
        </archive>
        <descriptorRefs>
            <descriptorRef>jar-with-dependencies</descriptorRef>
        </descriptorRefs>
    </configuration>
    <executions>
        <execution>
            <id>make-my-jar-with-dependencies</id>
            <phase>package</phase>
            <goals>
                <goal>single</goal>
            </goals>
        </execution>
    </executions>
</plugin>

<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-shade-plugin</artifactId>
    <version>2.4.3</version>
    <configuration>
        <shadedArtifactAttached>false</shadedArtifactAttached>
        <keepDependenciesWithProvidedScope>false</keepDependenciesWithProvidedScope>
        <transformers>
            <transformer implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
                <resource>META-INF/services/javax.ws.rs.ext.Providers</resource>
            </transformer>
            <transformer implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
                <resource>META-INF/spring.factories</resource>
            </transformer>
            <transformer implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
                <resource>META-INF/spring.handlers</resource>
            </transformer>
            <transformer implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
                <resource>META-INF/spring.schemas</resource>
            </transformer>
            <transformer implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
                <resource>META-INF/spring.tooling</resource>
            </transformer>
            <transformer implementation="org.apache.maven.plugins.shade.resource.ServicesResourceTransformer"/>
            <transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer"/>
            <transformer implementation="org.apache.maven.plugins.shade.resource.ApacheLicenseResourceTransformer">
            </transformer>
        </transformers>
    </configuration>
    <executions>
        <execution>
            <goals>
                <goal>shade</goal>
            </goals>
        </execution>
    </executions>
</plugin>