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

How can I create an executable JAR with dependencies using Maven?

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

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


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<build>
  <plugins>
    <plugin>
      maven-assembly-plugin</artifactId>
      <configuration>
       
          <manifest>
            <mainClass>fully.qualified.MainClass</mainClass>
          </manifest>
        </archive>
        <descriptorRefs>
          <descriptorRef>jar-with-dependencies</descriptorRef>
        </descriptorRefs>
      </configuration>
    </plugin>
  </plugins>
</build>

和你一起跑

1
mvn clean compile assembly:single

编译目标应该在组装之前添加:单个或其他情况下不包括您自己项目上的代码。

请参阅评论中的更多详细信息。

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
<plugin>
  maven-assembly-plugin</artifactId>
  <configuration>
   
      <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>


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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    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>
    maven-jar-plugin</artifactId>
    <configuration>
       
            <manifest>
                true</addClasspath>
                <classpathPrefix>lib/</classpathPrefix>
                <mainClass>theMainClass</mainClass>
            </manifest>
        </archive>
    </configuration>
</plugin>

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


我在博客上介绍了一些不同的方法。

请参阅带有ApacheMaven(WordPress)的可执行JAR

或带有maven示例(github)的可执行jar

笔记

这些利弊都是斯蒂芬提供的。

用于手动部署

  • 赞成的意见
  • 欺骗
    • 依赖项在最终的JAR中。

将依赖项复制到特定目录

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<plugin>
  <groupId>org.apache.maven.plugins</groupId>
  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可执行并知道类路径

1
2
3
4
5
6
7
8
9
10
11
12
13
<plugin>
  <groupId>org.apache.maven.plugins</groupId>
  maven-jar-plugin</artifactId>
  <configuration>
   
      <manifest>
        true</addClasspath>
        <classpathPrefix>${project.build.finalName}.lib/</classpathPrefix>
        <mainClass>${fully.qualified.main.class}</mainClass>
      </manifest>
    </archive>
  </configuration>
</plugin>

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

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

创建可部署的存档

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
<plugin>
  <groupId>org.apache.maven.plugins</groupId>
  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插件)。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
<plugin>
  <groupId>org.apache.maven.plugins</groupId>
  maven-assembly-plugin</artifactId>
  <executions>
    <execution>
      <phase>package</phase>
      <goals>
        <goal>single</goal>
      </goals>
      <configuration>
       
          <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阴影插件

  • 赞成的意见
  • 欺骗
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<plugin>
  <groupId>org.apache.maven.plugins</groupId>
  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>

你有一辆车。

Onejar Maven插件

  • 赞成的意见
  • 欺骗
    • 自2012年以来未得到积极支持。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<plugin>
  <!--groupId>org.dstovall</groupId--> <!-- not available on the central -->
  <groupId>com.jolira</groupId>
  onejar-maven-plugin</artifactId>
  <executions>
    <execution>
      <configuration>
        <mainClass>${fully.qualified.main.class}</mainClass>
        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引导Maven插件

  • 赞成的意见
  • 欺骗
    • 添加潜在的与Spring和Spring引导相关的类。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<plugin>
  <groupId>org.springframework.boot</groupId>
  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>

你有埃多克斯1〔8〕。


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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
<build>
    <plugins>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            maven-jar-plugin</artifactId>
            <configuration>
               
                    <manifest>
                        true</addClasspath>
                        <mainClass>fully.qualified.MainClass</mainClass>
                    </manifest>
                </archive>
            </configuration>
        </plugin>
        <plugin>
            maven-assembly-plugin</artifactId>
            <configuration>
                <descriptorRefs>
                    <descriptorRef>jar-with-dependencies</descriptorRef>
                </descriptorRefs>
            </configuration>
        </plugin>
    </plugins>
</build>

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
<project>
  [...]
  <build>
      <plugins>
          <plugin>
              maven-assembly-plugin</artifactId>
              <configuration>
                 
                      <manifest>
                          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>


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

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

见下面的例子

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
      <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>
            maven-shade-plugin</artifactId>
            <version>1.4</version>
            <executions>
                <execution>
                    <phase>package</phase>
                    <goals>
                        <goal>shade</goal>
                    </goals>
                    <configuration>
                       
                        <!-- 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>


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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<plugin>
    <groupId>org.dstovall</groupId>
    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>

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

1
2
3
4
5
6
<pluginRepositories>
    <pluginRepository>
        <id>onejar-maven-plugin.googlecode.com</id>
        <url>http://onejar-maven-plugin.googlecode.com/svn/mavenrepo</url>
    </pluginRepository>
</pluginRepositories>


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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
<build>
    <plugins>
        <plugin>
            maven-jar-plugin</artifactId>
            <configuration>
               
                    <manifest>
                        <mainClass>fully.qualified.MainClass</mainClass>
                    </manifest>
                </archive>
            </configuration>
        </plugin>
        <plugin>
            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>

如果您真的想重新打包单个结果JAR中的其他JAR内容,另一个选项是Maven程序集插件。它解包,然后通过true将所有内容重新打包到一个目录中。然后你会有第二次传球,把它塞进一个大罐子里。

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


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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
<build>
<defaultGoal>install</defaultGoal>
<plugins>
  <plugin>
    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>
    maven-jar-plugin</artifactId>
    <version>2.3.1</version>
    <configuration>
     
        <manifest>
          true</addClasspath>
          <mainClass>com.mycompany.package.MainClass</mainClass>
        </manifest>
      </archive>
    </configuration>
  </plugin>
  <plugin>
    maven-assembly-plugin</artifactId>
    <configuration>
      <descriptorRefs>
        <descriptorRef>jar-with-dependencies</descriptorRef>
      </descriptorRefs>
     
        <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程序集:single,然后您的具有依赖性的可执行jar文件将有望构建。您可以在切换到CD/.Target的输出(目标)目录时检查它,并启动一个类似于Java-JavaMavePark1.1-SnAPHOTH-JAR-WEXCENCENCI.jar的命令。

我用ApacheMaven 3.0.3测试了这个。


我仔细检查了所有这些响应,希望生成一个包含所有依赖项的胖的可执行jar,但没有一个能够正常工作。答案是shade插件,它非常简单和简单。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
    <plugin>
      <groupId>org.apache.maven.plugins</groupId>
      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


你可以把maven-shade-pluginmaven-jar-plugin结合起来。

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

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

1
2
3
4
5
6
7
8
9
10
11
12
13
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            maven-jar-plugin</artifactId>
            <version>2.3.2</version>
            <configuration>
               
                    <manifest>
                        true</addClasspath>
                        <mainClass>com.example.MyMainClass</mainClass>
                    </manifest>
                </archive>
            </configuration>
        </plugin>

最后通过调用以下命令创建可执行JAR:

1
mvn clean package shade:shade


您可以使用maven-shade插件构建一个如下所示的超级jar

1
2
3
4
5
6
7
8
9
10
11
12
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            maven-shade-plugin</artifactId>
            <executions>
                <execution>
                    <phase>package</phase>
                    <goals>
                        <goal>shade</goal>
                    </goals>
                </execution>
            </executions>
        </plugin>


这里有一个maven的可执行jar插件,我们在credit karma中使用。它创建了一个JAR JAR,其中的类加载器能够从嵌套JAR中加载类。这允许您在dev和prod中拥有相同的类路径,并且仍然将所有类保存在一个签名的jar文件中。

https://github.com/creditkarma/maven-exec-jar-plugin

下面是一篇博客文章,详细介绍了这个插件以及我们为什么创建它:https://engineering.creditkama.com/general-engineering/new-executable-jar-plugin-available-apache-maven/


刘肯在我看来是对的。Maven依赖插件允许您扩展所有依赖项,然后可以将其视为资源。这允许您将它们包含在主工件中。程序集插件的使用创建了一个二级工件,这很难修改——在我的例子中,我想添加自定义清单条目。我的POM结果是:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
<project>
 ...
 <build>
  <plugins>
   <plugin>
    <groupId>org.apache.maven.plugins</groupId>
    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
2
3
4
5
6
7
8
9
10
11
12
    <plugin>
                maven-dependency-plugin</artifactId>
                <executions>
                        <execution>
                                <id>unpack-dependencies</id>
                                <phase>generate-resources</phase>
                                <goals>
                                        <goal>unpack-dependencies</goal>
                                </goals>
                        </execution>
                </executions>
        </plugin>

解包必须处于"生成资源"阶段,因为如果处于包阶段,则不会作为资源包含在内。试试干净的包装,你会看到的。


使用Onejar插件将其构建为一个可执行的jar文件,其中打包了其中的所有依赖jar。这解决了我类似的问题。当使用程序集插件时,它将所有依赖jar解包到源文件夹中,并将它们重新打包为jar,它重写了我在代码中拥有相同类名的所有类似实现。Onejar是一个简单的解决方案。


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

尝试使用DescriptorID配置参数而不是描述符/描述符或DescriptorRef/DescriptorRef参数。

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

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

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

例子:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
        <!-- Use the assembly plugin to create a zip file of all our dependencies. -->
        <plugin>
            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>
                    TEST_SharedAssemblyDescriptor</artifactId>
                    <version>1.0.0-SNAPSHOT</version>
                </dependency>
            </dependencies>
        </plugin>

我不会像其他人以前那样直接回答这个问题,但我真的想知道将所有依赖项嵌入到项目的JAR中是否是一个好主意。

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

如果你完全独立使用它,为什么不呢?

但是如果您在其他环境中使用您的项目(比如在webapp中,或者放在其他jar所在的文件夹中),您的类路径中可能有jar副本(文件夹中的,jar中的)。也许不是出价协议,但我通常避免这样做。

一个好的选择:

  • 将应用程序部署为.zip/.war:存档包含项目的jar和所有相关jar;
  • 使用动态类加载器机制(请参阅Spring,或者您自己也可以很容易地做到这一点)来拥有项目的单个入口点(要启动的单个类-请参阅另一个答案上的清单机制),它将(动态地)添加到当前类路径中所有其他需要的jar。

像这样,在最后只有一个清单和一个"特殊的动态类加载器主目录"的情况下,您可以用以下方法开始您的项目:

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


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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
<build>
   <pluginManagement>
      <plugins>
         <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            maven-assembly-plugin</artifactId>
            <configuration>
               
                  <manifest>
                     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- Creating a Jar together with its dependency Jars into a single executable Jar file


如果您想从命令行本身获取if。只需从项目路径运行以下命令

MVN程序集:程序集


您也可以使用这个插件,它非常好,我使用它来打包jars http://sonatype.github.io/jarjar-maven-plug in/


对我有用的是:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
  <plugin>
    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>
    maven-jar-plugin</artifactId>
    <executions>
      <execution>
        <id>unpack-dependencies</id>
        <phase>package</phase>
      </execution>
    </executions>
    <configuration>
     
        <manifest>
          true</addClasspath>
          <classpathPrefix>lib/</classpathPrefix>
          <mainClass>SimpleKeyLogger</mainClass>
        </manifest>
      </archive>
    </configuration>
  </plugin>

我有一个特别的案例,因为我的依赖是系统一:

1
2
3
4
5
<dependency>
  ..
  <scope>system</scope>
  <systemPath>${project.basedir}/lib/myjar.jar</systemPath>
</dependency>

我已经更改了@user189057提供的代码,更改内容如下:1)maven依赖插件在"准备包"阶段执行2)我将解包类直接提取到"目标/类"


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

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

1)只需右键单击项目文件夹(在Eclipse中),然后选择Export

2)然后选择Java->Runnable Jar

3)将要求您选择JAR文件的位置。

4)最后,选择要运行的主方法的类,选择Package dependencies with the Jar file,点击Finish


这是我找到的最好方法:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
  <plugin>
    <groupId>org.apache.maven.plugins</groupId>
    maven-jar-plugin</artifactId>
    <version>2.4</version>
    <configuration>
     
        <manifest>
        true</addClasspath>
        <mainClass>com.myDomain.etc.MainClassName</mainClass>
        <classpathPrefix>dependency-jars/</classpathPrefix>
        </manifest>
      </archive>
    </configuration>
  </plugin>
  <plugin>
    <groupId>org.apache.maven.plugins</groupId>
    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参数。有了这个,我就可以这样启动我的应用程序:

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

我等着这对你们大家都有用。


我比较了本文中提到的树插件。我生成了2个jar和一个包含所有jar的目录。我比较了结果,肯定maven shade插件是最好的。我面临的挑战是,我有多个需要合并的Spring资源,以及JAX RS和JDBC服务。与Maven程序集插件相比,shade插件正确地合并了所有这些插件。在这种情况下,除非您将它们复制到自己的资源文件夹并手动合并一次,否则Spring将失败。两个插件都输出正确的依赖树。我有多个作用域,比如test、provide、compile等,这两个插件都跳过了测试和提供的作用域。它们都生成了相同的清单,但我可以使用它们的转换器用shade插件合并许可证。对于Maven依赖插件,当然您没有这些问题,因为JAR没有被提取出来。但是像其他人指出的那样,你需要携带一个额外的文件才能正常工作。下面是pom.xml的一个片段

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
            <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            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>
            maven-assembly-plugin</artifactId>
            <version>2.6</version>
            <configuration>
               
                    <manifest>
                        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>
            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>

对于任何想从uber jar中排除特定依赖项的人来说,这是一个适用于我的解决方案:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
<project...>
<dependencies>
        <dependency>
            <groupId>org.apache.spark</groupId>
            spark-core_2.11</artifactId>
            <version>1.6.1</version>
            <scope>provided</scope> <=============
        </dependency>
</dependencies>
<build>
        <plugins>
            <plugin>
                maven-assembly-plugin</artifactId>
                <configuration>
                    <descriptorRefs>
                        <descriptorRef>jar-with-dependencies</descriptorRef>
                    </descriptorRefs>
                   
                        <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程序集插件的配置,而是依赖项的属性。


已经有数百万个答案了,我想补充一下,如果您不需要向应用程序添加入口点,那么您不需要。例如,API可能不一定有main方法。

Maven插件配置

1
2
3
4
5
6
7
8
9
10
11
12
13
  <build>
    <finalName>log-enrichment</finalName>
    <plugins>
      <plugin>
        maven-assembly-plugin</artifactId>
        <configuration>
          <descriptorRefs>
            <descriptorRef>jar-with-dependencies</descriptorRef>
          </descriptorRefs>
        </configuration>
      </plugin>
    </plugins>
  </build>

建造

1
mvn clean compile assembly:single

验证

1
2
3
4
5
6
7
8
9
10
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/

添加到POM.XML:

1
2
3
4
5
  <dependency>
            <groupId>com.jolira</groupId>
            onejar-maven-plugin</artifactId>
            <version>1.4.4</version>
  </dependency>

1
2
3
4
5
6
7
8
9
10
11
12
<plugin>
       <groupId>com.jolira</groupId>
       onejar-maven-plugin</artifactId>
       <version>1.4.4</version>
       <executions>
              <execution>
                     <goals>
                         <goal>one-jar</goal>
                     </goals>
              </execution>
       </executions>
</plugin>

就是这样。下一个MVN包还将另外创建一个胖jar,包括所有依赖jar。


这也可以是一个选项,您将能够构建JAR文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<build>
    <plugins>
        <plugin>
            <!-- Build an executable JAR -->
            <groupId>org.apache.maven.plugins</groupId>
            maven-jar-plugin</artifactId>
            <version>2.4</version>
            <configuration>
               
                    <manifest>
                        true</addClasspath>
                        <classpathPrefix>lib/</classpathPrefix>
                        <mainClass>WordListDriver</mainClass>
                    </manifest>
                </archive>
            </configuration>
        </plugin>
    </plugins>
</build>

Maven程序集插件对我很有用。我花了几个小时在Maven依赖插件上,但无法使它工作。主要原因是我必须在配置部分明确地定义工件项,正如文档中所描述的那样,工件项应该包括在内。这里有一个例子,当你想使用它时,比如:mvn dependency:copy,其中没有包含任何工件项,但是它不起作用。


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
<build>
    <plugins>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            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>


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

The ideal solution is to include the jars in a lib folder and the manifest.mf file of the main jar include all the jars in classpath.

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


好吧,这就是我的解决方案。我知道它没有使用pom.xml文件。但是我的程序编写和运行在NETBeBes上遇到了问题,但是当我尝试JavaJavaMyjARFIL.jar时,它失败了。现在,我不完全理解Maven,我认为这就是为什么让NetBeans 8.0.2将我的JAR文件包含在库中以将它们放入JAR文件时遇到困难的原因。我在想我以前是如何在Eclipse中使用没有Maven的JAR文件的。

Maven可以编译所有依赖项和插件。不是网豆。(如果你能得到NETBeOne,并且能够使用Java.jar来做这件事,请告诉我如何(^ ^)v)

[解决-Linux版]通过打开终端。

然后

1
cd /MyRootDirectoryForMyProject

接下来

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

接下来

1
mvn install

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

1
MyJarFile-1.0-jar-with-dependencies.jar

现在

1
cd target

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

最后

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

请看

https://cwiki.apache.org/confluence/display/maven/lifecyclephasenotfoundexception

我将把这个解决方案发布到其他几个有类似问题的页面上。希望我能让别人从一周的挫折中解脱出来。


请使用图片演示查看此答案https://stackoverflow.com/a/35359756/5678086,以创建包含所有依赖项的完整包。