ChatGPT解决这个技术问题 Extra ChatGPT

如何使用 Maven 创建具有依赖关系的可执行 JAR?

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

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

请解释您所指的依赖插件的目标。我知道没有什么目标可以满足原始问题的要求:将所有依赖项 A)通过重新打包放入作者 jar 中,或 B)制作一个可执行 jar,该 jar 在 MANIFEST.MF 的类路径中包含其他依赖项
您可能会发现这很有用rationaljava.com/2015/02/…

8
8 revs, 8 users 31%
<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

编译目标应该在 assembly:single 之前添加,否则不包括您自己项目中的代码。

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

通常,此目标与自动执行的构建阶段相关联。这可确保在执行 mvn install 或执行部署/发布时构建 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>

谢谢@IAdapter。请注意,您应该始终事先进行编译,因为它只会将“目标/类”中的任何内容放入 JAR 中。这将确保 JAR 包含您最近对源代码所做的任何更改。因此,您应该执行以下操作:mvn clean compile assembly:single
我看到这不会将 jar 添加到 uber jar 中,而是将所有类文件添加到 jar 中。
提示:您还可以将元素 <appendAssemblyId>false</appendAssemblyId> 添加到 configuration 以避免名称中烦人的“-jar-with-dependencies”后缀
如果我没有 main 方法或类,我只需要一些随机的 java 文件作为 jar 怎么办?
@user10201743 只是提供一点上下文:Maven 中的 Everything 是一个插件。编译器? maven-compiler-plugin。测试? maven-surefire-plugin。这两个,包括程序集,是官方的 maven 插件,所以它们也可以被视为 maven 的一部分(尤其是因为,至少现在,它们三个都默认在你的有效 POM 中)。
D
Duncan Jones

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

<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。


有没有办法在不编写自定义类加载器的情况下使用此方法?我收到“ClassNotFoundException”。当我比较程序集插件时,我想我可以使用 maven-dependency-plugin 解包依赖项。有什么建议吗?
J
Jin Kwon

请参阅 executable-jar-with-maven-example (GitHub)

笔记

Stephan 提供了这些优点和缺点。

对于手动部署

优点

缺点 依赖项不在最终的 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}/${project.build.finalName}.lib</outputDirectory>
      </configuration>
    </execution>
  </executions>
</plugin>

使 Jar 可执行且可感知类路径

<plugin>
  <groupId>org.apache.maven.plugins</groupId>
  <artifactId>maven-jar-plugin</artifactId>
  <configuration>
    <archive>
      <manifest>
        <addClasspath>true</addClasspath>
        <classpathPrefix>${project.build.finalName}.lib/</classpathPrefix>
        <mainClass>${fully.qualified.main.class}</mainClass>
      </manifest>
    </archive>
  </configuration>
</plugin>

此时,jar 实际上可以使用外部类路径元素执行。

$ java -jar target/${project.build.finalName}.jar

制作可部署的档案

jar 文件只能与同级 ...lib/ 目录一起执行。我们需要制作档案以与目录及其内容一起部署。

<plugin>
  <groupId>org.apache.maven.plugins</groupId>
  <artifactId>maven-antrun-plugin</artifactId>
  <executions>
    <execution>
      <id>antrun-archive</id>
      <phase>package</phase>
      <goals>
        <goal>run</goal>
      </goals>
      <configuration>
        <target>
          <property name="final.name" value="${project.build.directory}/${project.build.finalName}"/>
          <property name="archive.includes" value="${project.build.finalName}.${project.packaging} ${project.build.finalName}.lib/*"/>
          <property name="tar.destfile" value="${final.name}.tar"/>
          <zip basedir="${project.build.directory}" destfile="${final.name}.zip" includes="${archive.includes}" />
          <tar basedir="${project.build.directory}" destfile="${tar.destfile}" includes="${archive.includes}" />
          <gzip src="${tar.destfile}" destfile="${tar.destfile}.gz" />
          <bzip2 src="${tar.destfile}" destfile="${tar.destfile}.bz2" />
        </target>
      </configuration>
    </execution>
  </executions>
</plugin>

现在您有了 target/${project.build.finalName}.(zip|tar|tar.bz2|tar.gz),每个都包含 jarlib/*

Apache Maven 程序集插件

优点

缺点 不支持类重定位(如果需要类重定位,请使用 maven-shade-plugin)。

没有类重定位支持(如果需要类重定位,请使用 maven-shade-plugin)。

<plugin>
  <groupId>org.apache.maven.plugins</groupId>
  <artifactId>maven-assembly-plugin</artifactId>
  <executions>
    <execution>
      <phase>package</phase>
      <goals>
        <goal>single</goal>
      </goals>
      <configuration>
        <archive>
          <manifest>
            <mainClass>${fully.qualified.main.class}</mainClass>
          </manifest>
        </archive>
        <descriptorRefs>
          <descriptorRef>jar-with-dependencies</descriptorRef>
        </descriptorRefs>
      </configuration>
    </execution>
  </executions>
</plugin>

您有 target/${project.bulid.finalName}-jar-with-dependencies.jar

Apache Maven 阴影插件

优点

缺点

<plugin>
  <groupId>org.apache.maven.plugins</groupId>
  <artifactId>maven-shade-plugin</artifactId>
  <executions>
    <execution>
      <goals>
        <goal>shade</goal>
      </goals>
      <configuration>
        <shadedArtifactAttached>true</shadedArtifactAttached>
        <transformers>
          <transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
            <mainClass>${fully.qualified.main.class}</mainClass>
          </transformer>
        </transformers>
      </configuration>
    </execution>
  </executions>
</plugin>

您有 target/${project.build.finalName}-shaded.jar

onejar-maven-插件

优点

缺点 自 2012 年以来未得到积极支持。

自 2012 年以来未得到积极支持。

<plugin>
  <!--groupId>org.dstovall</groupId--> <!-- not available on the central -->
  <groupId>com.jolira</groupId>
  <artifactId>onejar-maven-plugin</artifactId>
  <executions>
    <execution>
      <configuration>
        <mainClass>${fully.qualified.main.class}</mainClass>
        <attachToBuild>true</attachToBuild>
        <!-- https://code.google.com/p/onejar-maven-plugin/issues/detail?id=8 -->
        <!--classifier>onejar</classifier-->
        <filename>${project.build.finalName}-onejar.${project.packaging}</filename>
      </configuration>
      <goals>
        <goal>one-jar</goal>
      </goals>
    </execution>
  </executions>
</plugin>

Spring Boot Maven 插件

优点

缺点 添加潜在的不必要的 Spring 和 Spring Boot 相关类。

添加潜在的不必要的 Spring 和 Spring Boot 相关类。

<plugin>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-maven-plugin</artifactId>
  <executions>
    <execution>
      <goals>
        <goal>repackage</goal>
      </goals>
      <configuration>
        <classifier>spring-boot</classifier>
        <mainClass>${fully.qualified.main.class}</mainClass>
      </configuration>
    </execution>
  </executions>
</plugin>

您有 target/${project.bulid.finalName}-spring-boot.jar


M
Mike Rylander

接受未回答的答案并重新格式化,我们有:

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

接下来,我建议将其作为构建的自然部分,而不是显式调用。要使其成为您构建的一个组成部分,请将此插件添加到您的 pom.xml 并将其绑定到 package 生命周期事件。但是,一个问题是,如果将它放在 pom.xml 中,则需要调用 assembly:single 目标,而如果从命令行手动执行,则需要调用“assembly:assembly”。

<project>
  [...]
  <build>
      <plugins>
          <plugin>
              <artifactId>maven-assembly-plugin</artifactId>
              <configuration>
                  <archive>
                      <manifest>
                          <addClasspath>true</addClasspath>
                          <mainClass>fully.qualified.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>
    [...]
  </build>
</project>

K
Kristian Glass

使用 maven-shade-plugin 将所有依赖项打包到一个 uber-jar 中。也可以通过指定主类来构建可执行jar。在尝试使用 maven-assembly 和 maven-jar 之后,我发现这个插件最适合我的需要。

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

请参阅下面的示例

      <plugins>
    <!-- This plugin provides the capability to package the artifact in an uber-jar, 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 jars-->
                            <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>

P
Paul Rooney

您可以使用 maven-shade 插件来构建一个 uber jar,如下所示

<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-shade-plugin</artifactId>
    <executions>
        <execution>
            <phase>package</phase>
            <goals>
                <goal>shade</goal>
            </goals>
        </execution>
    </executions>
</plugin>

C
Community

长期使用 maven 程序集插件,但我找不到解决 "already added, skipping" 问题的方法。现在,我正在使用另一个插件 - onejar-maven-plugin。下面的示例(mvn package 构建 jar):

<plugin>
    <groupId>org.dstovall</groupId>
    <artifactId>onejar-maven-plugin</artifactId>
    <version>1.3.0</version>
    <executions>
        <execution>
            <configuration>
                <mainClass>com.company.MainClass</mainClass>
            </configuration>
            <goals>
                <goal>one-jar</goal>
            </goals>
        </execution>
    </executions>
</plugin>

您需要为该插件添加存储库:

<pluginRepositories>
    <pluginRepository>
        <id>onejar-maven-plugin.googlecode.com</id>
        <url>http://onejar-maven-plugin.googlecode.com/svn/mavenrepo</url>
    </pluginRepository>
</pluginRepositories>

佚名

您可以使用 maven-dependency-plugin,但问题是如何创建可执行 JAR。为此,需要对 Matthew Franglen 的响应进行以下更改(顺便说一句,从干净的目标开始时使用依赖插件需要更长的时间来构建):

<build>
    <plugins>
        <plugin>
            <artifactId>maven-jar-plugin</artifactId>
            <configuration>
                <archive>
                    <manifest>
                        <mainClass>fully.qualified.MainClass</mainClass>
                    </manifest>
                </archive>
            </configuration>
        </plugin>
        <plugin>
            <artifactId>maven-dependency-plugin</artifactId>
            <executions>
                <execution>
                    <id>unpack-dependencies</id>
                    <phase>package</phase>
                    <goals>
                        <goal>unpack-dependencies</goal>
                    </goals>
                </execution>
            </executions>
        </plugin>
    </plugins>
    <resources>
        <resource>
            <directory>${basedir}/target/dependency</directory>
        </resource>
    </resources>
</build>

B
Benny Neugebauer

您可以将以下内容添加到您的 pom.xml:

<build>
<defaultGoal>install</defaultGoal>
<plugins>
  <plugin>
    <artifactId>maven-compiler-plugin</artifactId>
    <version>2.3.2</version>
    <configuration>
      <source>1.6</source>
      <target>1.6</target>
    </configuration>
  </plugin>
  <plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-jar-plugin</artifactId>
    <version>2.3.1</version>
    <configuration>
      <archive>
        <manifest>
          <addClasspath>true</addClasspath>
          <mainClass>com.mycompany.package.MainClass</mainClass>
        </manifest>
      </archive>
    </configuration>
  </plugin>
  <plugin>
    <artifactId>maven-assembly-plugin</artifactId>
    <configuration>
      <descriptorRefs>
        <descriptorRef>jar-with-dependencies</descriptorRef>
      </descriptorRefs>
      <archive>
        <manifest>
          <mainClass>com.mycompany.package.MainClass</mainClass>
        </manifest>
      </archive>
    </configuration>
    <executions>
      <execution>
        <id>make-my-jar-with-dependencies</id>
        <phase>package</phase>
        <goals>
          <goal>single</goal>
        </goals>
      </execution>
    </executions>
  </plugin>
</plugins>
</build>

之后,您必须通过控制台切换到 pom.xml 所在的目录。然后你必须执行 mvn assembly:single 然后你的可执行 JAR 文件与依赖项将有望被构建。您可以在使用 cd ./target 切换到输出(目标)目录并使用类似于 java -jar mavenproject1-1.0-SNAPSHOT-jar-with-dependencies.jar 的命令启动 jar 时检查它。

我用 Apache Maven 3.0.3 对此进行了测试。


M
Matthew McCullough

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

Another option is the OneJar plugin。这一步完成了上述重新打包操作。


d
dsutherland

我浏览了这些响应中的每一个,希望制作一个包含所有依赖项的胖可执行 jar,但它们都不能正常工作。答案是阴影插件,它非常简单明了。

    <plugin>
      <groupId>org.apache.maven.plugins</groupId>
      <artifactId>maven-shade-plugin</artifactId>
      <version>2.3</version>
      <executions>
         <!-- Run shade goal on package phase -->
        <execution>
        <phase>package</phase>
        <goals>
            <goal>shade</goal>
        </goals>
        <configuration>
          <transformers>
             <transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
                <mainClass>path.to.MainClass</mainClass>
             </transformer>
          </transformers>
        </configuration>
          </execution>
      </executions>
    </plugin>

请注意,您的依赖项需要具有编译或运行时范围才能正常工作。

This example came from mkyong.com


n
n00begon

您可以组合 maven-shade-pluginmaven-jar-plugin

maven-shade-plugin 将您的类和所有依赖项打包在一个 jar 文件中。

配置 maven-jar-plugin 以指定可执行 jar 的主类(请参阅设置类路径,“使 Jar 可执行”一章)。

maven-jar-plugin 的示例 POM 配置:

        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-jar-plugin</artifactId>
            <version>2.3.2</version>
            <configuration>
                <archive>
                    <manifest>
                        <addClasspath>true</addClasspath>
                        <mainClass>com.example.MyMainClass</mainClass>
                    </manifest>
                </archive>
            </configuration>
        </plugin>

最后通过调用创建可执行jar:

mvn clean package shade:shade

Shade 插件现在可以在清单中指定 Main-Class 条目:maven.apache.org/plugins/maven-shade-plugin/examples/…
c
cb4

它将像这样工作:

<plugin>
    <artifactId>maven-dependency-plugin</artifactId>
    <executions>
        <execution>
            <id>unpack-dependencies</id>
            <phase>generate-resources</phase>
            <goals>
                <goal>unpack-dependencies</goal>
            </goals>
        </execution>
    </executions>
</plugin>

解包必须在 generate-resources 阶段,否则它不会被包含为资源。


得到这个问题:org.apache.maven.lifecycle.LifecycleExecutionException: Failed to execute goal org.apache.maven.plugins:maven-dependency-plugin:3.1.2:unpack-dependencies (unpack-dependencies) on project services: Unknown archiver类型
M
Matthew Franglen

在我看来,Ken Liu 是对的。 maven 依赖插件允许您扩展所有依赖项,然后您可以将其视为资源。这允许您将它们包含在主工件中。组装插件的使用创建了一个可能难以修改的辅助工件 - 在我的情况下,我想添加自定义清单条目。我的 pom 最终变成:

<project>
 ...
 <build>
  <plugins>
   <plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-dependency-plugin</artifactId>
    <executions>
     <execution>
      <id>unpack-dependencies</id>
      <phase>package</phase>
      <goals>
       <goal>unpack-dependencies</goal>
      </goals>
     </execution>
    </executions>
   </plugin>
  </plugins>
  ...
  <resources>
   <resource>
    <directory>${basedir}/target/dependency</directory>
    <targetPath>/</targetPath>
   </resource>
  </resources>
 </build>
 ...
</project>

n
n00begon

使用 maven-assembly-plugin-2.2.1 定位共享程序集文件有问题吗?

尝试使用descriptorId 配置参数而不是descriptors/descriptor 或descriptorRefs/descriptorRef 参数。

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

有关详细信息,请参阅 this

类: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>

A
Anoop Rai

为了解决这个问题,我们将使用 Maven 程序集插件,它将 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

http://jkoder.com/maven-creating-a-jar-together-with-its-dependency-jars-into-a-single-executable-jar-file/


S
SRG

我不会直接回答这个问题,因为其他人之前已经这样做了,但我真的想知道将所有依赖项嵌入到项目的 jar 本身中是否是个好主意。

我明白了这一点(易于部署/使用),但这取决于您的项目的用例(并且可能有替代方案(见下文))。

如果您完全独立使用它,为什么不呢。

但是,如果您在其他上下文中使用您的项目(例如在 web 应用程序中,或放在其他 jar 所在的文件夹中),您的类路径中可能有 jar 重复项(文件夹中的那些,jar 中的那个)。也许不是投标交易,但我通常会避免这种情况。

一个很好的选择:

将您的应用程序部署为 .zip / .war :存档包含您项目的 jar 和所有依赖的 jar;

使用动态类加载器机制(请参阅 Spring,或者您可以自己轻松地做到这一点)拥有项目的单个入口点(启动单个类 - 请参阅另一个答案的清单机制),这将(动态)添加到当前类路径所有其他需要的罐子。

像这样,最后只有一个清单和一个“特殊的动态类加载器主程序”,您可以使用以下命令开始您的项目:

java -jar ProjectMainJar.jar com.stackoverflow.projectName.MainDynamicClassLoaderClass

h
hd1

对我有用的是:

  <plugin>
    <artifactId>maven-dependency-plugin</artifactId>
    <executions>
      <execution>
        <id>unpack-dependencies</id>
        <phase>prepare-package</phase>
        <goals>
          <goal>unpack-dependencies</goal>
        </goals>
        <configuration>
          <outputDirectory>${project.build.directory}/classes</outputDirectory>
        </configuration>
      </execution>

    </executions>
  </plugin>


  <plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-jar-plugin</artifactId>
    <executions>
      <execution>
        <id>unpack-dependencies</id>
        <phase>package</phase>
      </execution>
    </executions>
    <configuration>
      <archive>
        <manifest>
          <addClasspath>true</addClasspath>
          <classpathPrefix>lib/</classpathPrefix>
          <mainClass>SimpleKeyLogger</mainClass>
        </manifest>
      </archive>
    </configuration>
  </plugin>

我有特殊情况,因为我的依赖是系统一:

<dependency>
  ..
  <scope>system</scope>
  <systemPath>${project.basedir}/lib/myjar.jar</systemPath>
</dependency>

我已经更改了@user189057 提供的代码并进行了更改:1)maven-dependency-plugin 在“准备包”阶段执行 2)我将解压的类直接提取到“目标/类”


E
EliuX

这是我发现的最好方法:

  <plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-jar-plugin</artifactId>
    <version>2.4</version>
    <configuration>
      <archive>
        <manifest>
        <addClasspath>true</addClasspath>
        <mainClass>com.myDomain.etc.MainClassName</mainClass>
        <classpathPrefix>dependency-jars/</classpathPrefix>
        </manifest>
      </archive>
    </configuration>
  </plugin>
  <plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-dependency-plugin</artifactId>
    <version>2.5.1</version>
    <executions>
      <execution>
        <id>copy-dependencies</id>
        <phase>package</phase>
        <goals>
            <goal>copy-dependencies</goal>
        </goals>
        <configuration>
            <outputDirectory>
               ${project.build.directory}/dependency-jars/
            </outputDirectory>
        </configuration>
      </execution>
    </executions>
  </plugin>

使用此配置,所有依赖项都将位于 /dependency-jars。我的应用程序没有 Main 类,只有上下文类,但我的一个依赖项确实有一个 Main 类 (com.myDomain.etc.MainClassName),它启动 JMX 服务器并接收 startstop 参数。所以有了这个我能够像这样启动我的应用程序:

java -jar ./lib/TestApp-1.0-SNAPSHOT.jar start

我等待它对大家有用。


F
Fabio

我比较了这篇文章中提到的树插件。我生成了 2 个 jar 和一个包含所有 jar 的目录。我比较了结果,肯定 maven-shade-plugin 是最好的。我的挑战是我有多个需要合并的 spring 资源,以及 jax-rs 和 JDBC 服务。与 maven-assembly-plugin 相比,它们都被 shade 插件正确合并。在这种情况下,除非您将它们复制到自己的资源文件夹并手动合并一次,否则 spring 将失败。两个插件都输出正确的依赖树。我有多个范围,如测试、提供、编译等,两个插件都跳过了测试和提供的范围。他们都产生了相同的清单,但我能够使用他们的转换器将许可证与阴影插件合并。使用 maven-dependency-plugin 当然你没有这些问题,因为 jars 没有被提取。但就像其他人指出的那样,您需要携带一个额外的文件才能正常工作。这是 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>

u
user3083022

对于任何寻找从 uber-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-assembly-plugin 的配置,而是依赖项的属性。


您的意思是 maven-assembly-plugin 尊重为依赖项指定的范围,并且默认情况下仅包含运行时依赖项?它是否也为传递依赖关系解决并传递它?
p
prayagupa

已经有数百万个答案,如果您不需要将 entryPoint 添加到您的应用程序,我想添加您不需要 <mainClass>例如 API 可能不一定有 main 方法。

maven插件配置

  <build>
    <finalName>log-enrichment</finalName>
    <plugins>
      <plugin>
        <artifactId>maven-assembly-plugin</artifactId>
        <configuration>
          <descriptorRefs>
            <descriptorRef>jar-with-dependencies</descriptorRef>
          </descriptorRefs>
        </configuration>
      </plugin>
    </plugins>
  </build>

建造

mvn clean compile assembly:single

核实

ll target/
total 35100
drwxrwx--- 1 root vboxsf     4096 Sep 29 16:25 ./
drwxrwx--- 1 root vboxsf     4096 Sep 29 16:25 ../
drwxrwx--- 1 root vboxsf        0 Sep 29 16:08 archive-tmp/
drwxrwx--- 1 root vboxsf        0 Sep 29 16:25 classes/
drwxrwx--- 1 root vboxsf        0 Sep 29 16:25 generated-sources/
drwxrwx--- 1 root vboxsf        0 Sep 29 16:25 generated-test-sources/
-rwxrwx--- 1 root vboxsf 35929841 Sep 29 16:10 log-enrichment-jar-with-dependencies.jar*
drwxrwx--- 1 root vboxsf        0 Sep 29 16:08 maven-status/

I
Ihor Patsian

要从命令行本身创建可执行 JAR,只需从项目路径运行以下命令:

mvn assembly:assembly

我认为你仍然需要在 pom.xml 中做一些事情,否则你会得到 Error reading assemblies: No assembly descriptors found.。无论如何,这就是发生在我身上的事情。
R
Rocky Inde

我在这里尝试了投票最多的答案,并且能够让 jar 可运行。但是程序没有正确运行。我不知道是什么原因。当我尝试从 Eclipse 运行时,我得到了不同的结果,但是当我从命令行运行 jar 时,我得到了不同的结果(它因程序特定的运行时错误而崩溃)。

我有与 OP 类似的要求,只是我的项目有太多(Maven)依赖项。幸运的是,唯一对我有用的解决方案是使用 Eclipse。非常简单,非常直接。这不是针对 OP 的解决方案,而是针对具有类似需求但具有许多 Maven 依赖项的人的解决方案,

1) 只需右键单击您的项目文件夹(在 Eclipse 中)并选择 Export

2) 然后选择 Java -> Runnable Jar

3) 系统会要求您选择 jar 文件的位置

4) 最后,选择具有您要运行的 Main 方法的类并选择 Package dependencies with the Jar file 并单击 Finish


s
salmanbw

这也可以是一个选项,您将能够构建您的 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>

B
Biswajit Roy

添加到 pom.xml:

  <dependency>
            <groupId>com.jolira</groupId>
            <artifactId>onejar-maven-plugin</artifactId>
            <version>1.4.4</version>
  </dependency>

<plugin>
       <groupId>com.jolira</groupId>
       <artifactId>onejar-maven-plugin</artifactId>
       <version>1.4.4</version>
       <executions>
              <execution>
                     <goals>
                         <goal>one-jar</goal>
                     </goals>
              </execution>
       </executions>
</plugin>

而已。下一个 mvn 包还会额外创建一个 fat jar,包括所有依赖 jar。


A
Akshay Patel

尝试了多种解决方案,但在我们想要创建一个不可执行的胖 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


c
cb4

我希望我的经验可以帮助别人。我想将我的应用程序 Spring(使用 CAS 客户端)迁移到 Spring Boot 1.5。我遇到了很多问题,例如:

没有主要清单属性,在 target/cas-client-web.jar

我试图制作一个具有所有依赖项的独特 jar。在互联网上搜索后,我可以用以下几行来做到这一点:

         <plugin>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-maven-plugin</artifactId>
            <configuration>
                <fork>true</fork>
                <mainClass>${start-class}</mainClass>
            </configuration>
            <executions>
                <execution>
                    <goals>
                        <goal>repackage</goal>
                    </goals>
                </execution>
            </executions>
        </plugin>
        <plugin>
            <artifactId>maven-assembly-plugin</artifactId>
            <executions>
                <execution>
                    <phase>package</phase>
                    <goals>
                        <goal>single</goal>
                    </goals>
                </execution>
            </executions>
            <configuration>
                <archive>
                    <manifest>
                        <addClasspath>true</addClasspath>
                        <mainClass>${start-class}</mainClass>
                    </manifest>
                </archive>
                <descriptorRefs>
                    <descriptorRef>jar-with-dependencies</descriptorRef>
                </descriptorRefs>
            </configuration>
        </plugin>

start-class 是我的主要课程:

<properties>
    <java.version>1.8</java.version>
    <start-class>com.test.Application</start-class>
</properties>

我的申请是:

package com.test;

import java.util.Arrays;

import com.test.TestProperties;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean;


@SpringBootApplication
@EnableAutoConfiguration
@EnableConfigurationProperties({TestProperties.class})
public class Application {

public static void main(String[] args) {
    SpringApplication.run(Application.class, args);
}

@Bean
public CommandLineRunner commandLineRunner(ApplicationContext ctx) {
    return args -> {

        System.out.println("Let's inspect the beans provided by Spring Boot:");

        String[] beanNames = ctx.getBeanDefinitionNames();
        Arrays.sort(beanNames);
        for (String beanName : beanNames) {
            System.out.println(beanName);
        }

    };
}

}

C
Chris

maven-assembly-plugin 对我很有用。我花了几个小时使用 maven-dependency-plugin 并且无法使其工作。主要原因是我必须在配置部分明确定义应包含的工件项,如 documentation 中所述。当您想使用它时,有一个示例:mvn dependency:copy,其中不包含任何 artifactItems 但它不起作用。


J
Jan Ziegler

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

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

正是在这里描述了这一点:https://caffebig.wordpress.com/2013/04/05/executable-jar-file-with-dependent-jars-using-maven/