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


2396

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

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


14
请解释您所指的依赖插件的目标。我不知道最初目标所要求的目标是什么:将所有依赖项(要么通过重新包装放入作者jar中),要么将B)制成一个在MANIFEST.MF类路径中具有其他依赖关系的可执行jar
Matthew McCullough

2
您可能会发现此有用的Rationaljava.com/2015/02/…–


Answers:


2358
<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:single之前添加,否则不包括您自己项目中的代码。

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


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

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

22
谢谢@IAdapter。请注意,您应该始终事先进行编译,因为它只会将JAR的“目标/类”中的内容放入。这将确保JAR包括您最近对源代码所做的任何更改。因此,您应该执行以下操作:mvn clean compile assembly:single
迈克尔

10
我已经编辑了包含相位绑定的问题。我删除了已弃用的组装目标,因为没有人需要知道这一点。
Duncan Jones

2
我看到这不会将jar添加到uber jar中,而是仅将所有类文件添加到jar中。
pitchblack408 2015年

170
提示:您也可以将元素添加<appendAssemblyId>false</appendAssemblyId>到中,configuration以避免名称中令人讨厌的“ -jar-with-dependencies”后缀
maxivis 2015年

6
忘了compile,你被搞砸了。
祈祷

349

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

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


3
+1好。我使用maven-dependency-plugin而不是maven-assembly-plugin的原因是,我还使用了buildnumber-maven-plugin,因此可以将版本号分别存储在每个jar的清单中。
PapaFreud 2011年

17
我喜欢您的解决方案。我使用${project.build.directory}/classes/libas作为outputDirectory一个主.jar,其中包含所有依赖项,但是-如何添加自定义类加载代码以加载此jar?我需要像这样执行工作java -jar main-jar-with-deps.jar。这可能吗 ?
marioosh 2012年

3
@AndréAronsen,我使用此解决方案将依赖项添加到了jar的lib文件夹中,但是我总是会发现类未找到异常,请您告诉我如何解决。
Mahmoud Saleh 2012年

11
+1给你!看起来maven程序集插件'jar-with-dependencies'不能很好地工作。我在生成的jar中缺少META-INF / spring.schemas中的某些条目。因此,我取消了jar-with-dependencies,并在上面使用了您的解决方案。很好,谢谢!!!
德里克(Derek)

9
对于遇到此问题的其他任何人,您必须将lib文件夹包含在与jar相同的目录中,无论将jar传输到哪个目录。
Sparticles 2014年

224

我在博客上写了一些不同的方法来做到这一点。

参见带有Apache Maven的可执行Jar(WordPress)

可执行文件罐与Maven示例(GitHub)

笔记

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


对于手动部署

  • 优点
  • 缺点
    • 依赖性超出了最终的范围。

将依赖项复制到特定目录

<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可执行并具有Classpath意识

<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实际上可以使用外部classpath元素执行。

$ 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 Assembly插件

  • 优点
  • 缺点
    • 不支持类重定位(如果需要类重定位,请使用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 Shade插件

  • 优点
  • 缺点
<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-plugin

  • 优点
  • 缺点
    • 自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相关类。
<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


2
@caiohamamura您可以克隆GitHub存储库并查看所有配置文件的工作方式。
Jin Kwon's

问题出在我使用的软件包中:stackoverflow.com/a/12622037/2548351
caiohamamura

1
我认为这可能是该主题的最完整答案。
彼得·博德纳(PetrBodnár),

139

采纳未答复的答案并重新格式化,我们有:

<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生命周期事件。但是,要注意的是,assembly:single如果将其放入pom.xml中,则需要调用该目标,而如果从命令行手动执行该目标,则需要调用“ 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>

10
在此答案中使用该方法会导致以下错误消息:当尝试使用“ java -jar <jar文件>”
Elmo

3
需要maven-jar-plugin的存档部分<archive> <manifest> <addClasspath> true </ addClasspath> <mainClass> fully.qualified.MainClass </ mainClass> </ manifest> </ archive>
Rade_303

4
抱歉,这个答案是完全错误的,mainClass标记必须在maven-assembly-plugin条目上,因为您在打包目标期间就调用了它
Alex Lehmann 2012年

我很惊讶,为什么在mvn archetype:generate命令之后pom.xml不能包含这个?每当我创建一个新的Maven项目时,手动复制粘贴都会很烦人……
wintermute 2016年

我有点没有主要的方法或类,我只是具有功能的类。我如何制作罐子并使用它
帕拉德

97

使用maven-shade-plugin将所有依赖项打包到一个uber-jar中。通过指定主类,它还可用于构建可执行jar。在尝试使用maven-assembly和maven-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>

那么,既然bcprov-jdk15.jar已从着色过程中排除,那么它如何在运行时进入类路径?
安德鲁·斯旺

它被cxf-rt-ws-security所拉扯,这是我依赖的一部分
Vijay Katam

以前从未听说过此插件,但是它用罐子里的spring.handlers解决了我的问题。谢谢!
亚历山大·泰勒斯

11
那些获得安全性例外的人将DSA排除在清单之外。检查maven.apache.org/plugins/maven-shade-plugin/examples/...
ruhsuzbaykus

+1我过去曾经使用过minijar:ueberjar,但是现在不赞成使用minijar插件,而是将其替换为shade
rds

19

长期使用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>

如何摆脱输出中多余的消息?
亚历山大

17

您可以使用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>

16

您可以使用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>

但是,这将如何部署回购呢?
Francesco Gualazzi '18


14

您可以将以下内容添加到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对此进行了测试。


13

我遍历了所有这些响应,以寻找一个包含所有依赖项的胖可执行jar,但它们均无法正常工作。答案是shade插件,它非常简单明了。

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

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

这个例子来自mkyong.com


当我修正此问题时,您介意更新您的评论吗?发布之前,我没有考虑过您的想法,而是在看到您的评论后迅速做出了修正
-dsutherland

2
plugin元素进去pom.xmlbuild/plugins
isapir

12

您可以将maven-shade-plugin和组合在一起maven-jar-plugin

  • maven-shade-plugin包将您的类和所有依赖项打包在一个jar文件中。
  • 配置,maven-jar-plugin以指定可执行jar的主类(请参见“ 设置类路径”,“使Jar可执行文件”一章)。

POM配置示例maven-jar-plugin

        <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

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

9

刘坚认为是对的。Maven依赖插件允许您扩展所有依赖,然后可以将其视为资源。这使您可以将它们包括在工件中。使用Assembly插件会创建一个很难修改的辅助工件-就我而言,我想添加自定义清单条目。我的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>

1
非常好!不过,使用generate-resources阶段进行解压缩会更好吗?
nawroth

9

应该是这样的:

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

拆包必须处于“生成资源”阶段,因为如果处于打包阶段,则不会包含在资源中。尝试清洁包装,您会看到的。


7

使用maven-assembly-plugin-2.2.1定位共享程序集文件时出现问题?

尝试使用描述符Id配置参数代替描述符/描述符或descriptorRefs / descriptorRef参数。

它们都不满足您的需要:在classpath上查找文件。当然,您需要添加共享程序集驻留在maven-assembly-plugin的类路径上的包(请参见下文)。如果您使用的是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>

7

为了解决此问题,我们将使用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/


5

我不会像其他人以前已经做过的那样直接回答这个问题,但是我真的很想知道将所有依赖项嵌入项目jar本身是否是一个好主意。

我明白了这一点(易于部署/使用),但这取决于您的项目的用例(并且可能有其他选择(请参见下文))。

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

但是,如果您在其他上下文中使用您的项目(例如在Web应用程序中,或放在其他jar所在的文件夹中),则您的类路径中可能有jar副本(文件夹中的副本,jar中的副本)。也许不是出价协议,但我通常会避免这种情况。

一个不错的选择:

  • 将您的应用程序部署为.zip / .war:归档文件包含项目的jar和所有相关的jar;
  • 使用动态的类加载器机制(请参见Spring,或者您也可以轻松地做到这一点)来使项目具有单个入口点(单个类即可开始-请参见其他答案的Manifest机制),这将(动态)添加到当前的classpath以及所有其他需要的jar。

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

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

1
那么如何将项目的jar和所有相关的jar放入存档中?

4

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

mvn assembly:assembly

3
我认为您仍然需要做一些事情,pom.xml否则您将得到Error reading assemblies: No assembly descriptors found.。无论如何,那对我来说就是这样。
Sridhar Sarnobat

3

这是我发现的最好方法:

  <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

我等待对您所有人有用。


3

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

2

对我有用的是:

  <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)在“ prepare-package”阶段执行maven-dependency-plugin 2)我将解压后的类直接提取到“ target / classes”


2

我在这里尝试了投票最多的答案,并且能够使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


2

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

2

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


2

已经有数百万个答案,<mainClass>如果您不需要在应用程序中添加entryPoint ,我想添加您不需要的答案。例如,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/

2

添加到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软件包还将另外创建一个胖子jar,包括所有依赖项jar。


1

Maven组装插件对我来说很棒。我花了几个小时使用了maven-dependency-plugin,但无法正常工作。主要原因是我必须在配置部分中明确定义应包含在文档中所描述的工件项目。有一个示例,用于您想要使用它的情况:mvn dependency:copy,其中不包含任何artifactItems,但它不起作用。


1

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

理想的解决方案是将这些jar包含在lib文件夹中,而主jar的manifest.mf文件则将所有jar包含在classpath中。

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


0
<build>
    <plugins>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-assembly-plugin</artifactId>
            <version>2.4.1</version>
            <configuration>
                <!-- get all project dependencies -->
                <descriptorRefs>
                    <descriptorRef>jar-with-dependencies</descriptorRef>
                </descriptorRefs>
            </configuration>
            <executions>
                <execution>
                    <id>make-assembly</id>
                    <!-- bind to the packaging phase -->
                    <phase>package</phase>
                    <goals>
                        <goal>single</goal>
                    </goals>
                </execution>
            </executions>
        </plugin>
    </plugins>
</build>

1
需要对此进行更多解释;这些评论仅仅是文档,还是需要在这些评论的位置放置其他选项?
马克·斯图尔特

-2

好的,这就是我的解决方案。我知道它没有使用pom.xml文件。但是我遇到了我的程序无法在Netbeans上编译和运行的问题,但是当我尝试Java -jar MyJarFile.jar时却失败了。现在,我还不完全了解Maven,我认为这就是为什么让Netbeans 8.0.2将我的jar文件包含在库中以将其放入jar文件时遇到麻烦。我在考虑如何在Eclipse中不使用Maven的情况下使用jar文件。

Maven可以编译所有的dependanices和插件。不是Netbeans。(如果可以获取Netbeans并能够使用java .jar进行此操作,请告诉我如何(^。^)v)

通过打开终端来[已解决-对于Linux]。

然后

cd /MyRootDirectoryForMyProject

下一个

mvn org.apache.maven.plugins:maven-compiler-plugin:compile

下一个

mvn install

这将在目标目录中创建jar文件。

MyJarFile-1.0-jar-with-dependencies.jar

现在

cd target

(您可能需要运行:chmod +x MyJarFile-1.0-jar-with-dependencies.jar

最后

java -jar MyJarFile-1.0-jar-with-dependencies.jar

请参阅

https://cwiki.apache.org/confluence/display/MAVEN/LifecyclePhaseNotFoundException

我会将这个解决方案发布在其他有类似问题的页面上。希望我可以摆脱一个星期的挫败感。


2
尝试打开使用Netbeans创建的Maven项目。Netbeans的基本规则始终是创建一个Maven项目,而不是创建“ Java应用程序”。添加maven-shade-plugin就像答案之一。奇迹般有效。
rjdkolb
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.