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

soe*_*rno 2276 java build-automation build-process maven-2 executable-jar

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

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

IAd*_*ter 2229

<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>
Run Code Online (Sandbox Code Playgroud)

你运行它

mvn clean compile assembly:single
Run Code Online (Sandbox Code Playgroud)

应该在汇编之前添加编译目标:单个或者不包括您自己项目中的代码.

在评论中查看更多详情.


通常,此目标与构建阶段相关联,以自动执行.这可确保在执行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>
Run Code Online (Sandbox Code Playgroud)

  • 提示:您还可以在`configuration`中添加元素`<appendAssemblyId> false </ appendAssemblyId>`,以避免名称中带有令人讨厌的"-jar-with-dependencies"后缀 (146认同)
  • 谢谢@IAdapter.请注意,您应该事先进行编译,因为它只会在JAR中放入"target/classes"中的内容.这将确保JAR包含您最近对源代码所做的任何更改.所以,你应该做的事情:`mvn clean compile assembly:single`. (19认同)
  • 我编辑了问题以包括相位绑定.我删除了已弃用的程序集目标,因为没有人需要知道这一点. (9认同)
  • 忘记`编译`,你搞砸了. (4认同)
  • @user10201743 只是提供一点背景信息:Maven 中的 _Everything_ 是一个插件。编译器?`maven-compiler-plugin`。测试?`maven-surefire-plugin`。这两个,包括程序集,是官方的 maven 插件,因此它们也可以被视为 maven 的一部分(尤其是因为,至少现在,默认情况下,这三个插件都在您的有效 POM 中)。 (4认同)
  • 我看到这不会将jar添加到uber jar中,而只是将所有类文件添加到jar中. (2认同)
  • maven 程序集插件可能会引入一些问题,因为可能会覆盖一些依赖项,所以我不能告诉你使用它!使用 maven Shade 插件,这对我们来说非常有用。我们花了几天时间发现 Maven 程序集插件覆盖了一些破坏应用程序 jar 的依赖项。看看那里:https://www.mkyong.com/maven/create-a-fat-jar-file-maven-shade-plugin/ (2认同)
  • 如果我没有main方法或类,我只需要一些随机的Java文件作为jar怎么办? (2认同)
  • 这不是可执行的 (2认同)

小智 334

您可以使用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>
Run Code Online (Sandbox Code Playgroud)

或者使用${project.build.directory}/classes/libOutputDirectory将所有jar文件集成到主jar中,但是您需要添加自定义类加载代码来加载jar.

  • 我喜欢你的解决方案.我使用`$ {project.build.directory}/classes/lib`作为`outputDirectory`来拥有一个包含所有依赖项的主.jar,但是 - 如何添加自定义类加载代码来加载这个jar?我需要像以下那样执行工作:`java -jar main-jar-with-deps.jar`.这可能吗 ? (14认同)
  • 给你+1!看起来像maven程序集插件'jar-with-dependencies'并不能很好地工作.我在生成的jar中错过了META-INF/spring.schemas中的一些条目.所以我废弃了依赖jar的jar并使用了上面的解决方案.很好,谢谢!!! (10认同)
  • 对于遇到此问题的任何其他人,您必须将jar文件夹包含在与jar一起运送jar的同一目录中. (8认同)
  • +1优秀.我使用maven-dependency-plugin而不是maven-assembly-plugin的原因是我还使用了buildnumber-maven-plugin,这样我就可以将版本号分别存储在每个jar的清单中. (3认同)
  • @AndréAronsen,我使用这个解决方案在jar里面的lib文件夹中添加依赖项,但我总是得到类找不到异常,你能告诉我如何修复它. (3认同)
  • +1,还要在maven-dependency-plugin的配置标记内添加<includeScope> compile </ includeScope>,因此它不会添加像junit这样的测试依赖项.请参阅http://stackoverflow.com/questions/8310539/how-to-copy-dependencies-jars-without-test-jars-to-a-directory-using-maven (3认同)

Jin*_*won 197

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

请参阅使用Apache Maven的可执行jar(WordPress)

或者可执行jar-with-maven-example(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>
Run Code Online (Sandbox Code Playgroud)

使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>
Run Code Online (Sandbox Code Playgroud)

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

$ java -jar target/${project.build.finalName}.jar
Run Code Online (Sandbox Code Playgroud)

制作可部署的档案

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>
Run Code Online (Sandbox Code Playgroud)

现在你有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>
Run Code Online (Sandbox Code Playgroud)

你有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>
Run Code Online (Sandbox Code Playgroud)

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


onejar - Maven的插件

  • 优点
  • 缺点
    • 自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>
Run Code Online (Sandbox Code Playgroud)

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>
Run Code Online (Sandbox Code Playgroud)

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

  • 这仍然非常有帮助 (3认同)

Mat*_*ugh 136

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

<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>
Run Code Online (Sandbox Code Playgroud)

接下来,我建议将其作为构建的自然部分,而不是明确调用.要使其成为构建中不可或缺的一部分,请将此插件添加到您的插件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>
Run Code Online (Sandbox Code Playgroud)

  • 使用此答案中的方法会导致以下错误消息:'尝试使用'java -jar <jar file>'运行JAR时,无法从<jar file>'加载Main-Class清单属性 (10认同)
  • 对不起,这个答案是完全错误的,mainClass标签必须在maven-assembly-plugin条目上,因为你在包目标期间调用它 (4认同)
  • 需要存档部分maven-jar-plugin <archive> <manifest> <addClasspath> true </ addClasspath> <mainClass> fully.qualified.MainClass </ mainClass> </ manifest> </ archive> (3认同)

Vij*_*tam 96

使用maven-shade-plugin将所有依赖项打包到一个超级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>
Run Code Online (Sandbox Code Playgroud)

  • 那些获得安全例外的人将DSA排除在Manifest之外.查看http://maven.apache.org/plugins/maven-shade-plugin/examples/includes-excludes.html (11认同)

mar*_*osh 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>
Run Code Online (Sandbox Code Playgroud)

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

<pluginRepositories>
    <pluginRepository>
        <id>onejar-maven-plugin.googlecode.com</id>
        <url>http://onejar-maven-plugin.googlecode.com/svn/mavenrepo</url>
    </pluginRepository>
</pluginRepositories>
Run Code Online (Sandbox Code Playgroud)


小智 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>
Run Code Online (Sandbox Code Playgroud)


Mat*_*ugh 15

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

另一个选择是OneJar插件.这将一步完成上述重新打包操作.


Ben*_*uer 13

您可以将以下内容添加到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>
Run Code Online (Sandbox Code Playgroud)

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

我用Apache Maven 3.0.3测试了这个.


dsu*_*and 12

我经历了这些响应中的每一个,希望制作一个包含所有依赖项的胖可执行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>
Run Code Online (Sandbox Code Playgroud)

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

这个例子来自mkyong.com

  • 插件元素在build / plugins下的pom.xml中。 (2认同)

Oli*_*ver 11

你可以结合maven-shade-pluginmaven-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>
Run Code Online (Sandbox Code Playgroud)

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

mvn clean package shade:shade
Run Code Online (Sandbox Code Playgroud)

  • Shade插件现在可以在清单中指定Main-Class条目:http://maven.apache.org/plugins/maven-shade-plugin/examples/executable-jar.html (3认同)

Min*_*sha 11

您可以使用maven-shade插件来构建如下所示的超级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>
Run Code Online (Sandbox Code Playgroud)


Mat*_*len 9

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>
Run Code Online (Sandbox Code Playgroud)


小智 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>
Run Code Online (Sandbox Code Playgroud)

解包必须处于生成资源阶段,因为如果处于打包阶段,则不会将其作为资源包含在内.尝试清洁包装,你会看到.


jch*_*nes 9

这是我们在Credit Karma使用的Maven的可执行jar插件.它创建了一个jar罐,其中包含一个能够从嵌套jar加载类的类加载器.这允许您在dev和prod中具有相同的类路径,并且仍将所有类保留在单个签名的jar文件中.

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

这里有一篇博客文章,详细介绍了插件及其制作原因:https: //engineering.creditkarma.com/general-engineering/new-executable-jar-plugin-available-apache-maven/


小智 7

使用onejar插件将其构建为一个可执行jar文件,该文件将所有依赖jar包装在其中.这解决了我的问题,与此类似.当使用程序集插件时,它将所有依赖jar解压缩到源文件夹中并将它们重新打包为jar,它已经覆盖了我在代码中具有相同类名的所有类似实现.onejar在这里是一个简单的解决方案.


小智 7

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

尝试使用descriptorId配置参数而不是descriptors/descriptor或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>
Run Code Online (Sandbox Code Playgroud)


Fab*_*bio 7

我比较了这篇文章中提到的树插件。我生成了两个 JAR 文件和一个包含所有 JAR 文件的目录。我比较了结果,maven-shade-plugin绝对是最好的。

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

两个插件都输出正确的依赖树。我有多个范围,如测试、提供、编译等。两个插件都跳过了测试和提供。他们都生成了相同的清单,但我能够使用他们的变压器将许可证与阴影插件合并。使用maven-dependency-plugin当然不会遇到这些问题,因为 JAR 文件不会被提取。但正如其他人指出的那样,您需要携带一个额外的文件才能正常工作。

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

<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-dependency-plugin</artifactId>
    <executions>
        <execution>
            <id>copy-dependencies</id>
            <phase>prepare-package</phase>
            <goals>
                <goal>copy-dependencies</goal>
            </goals>
            <configuration>
                <outputDirectory>${project.build.directory}/lib</outputDirectory>
                <includeScope>compile</includeScope>
                <excludeTransitive>true</excludeTransitive>
                <overWriteReleases>false</overWriteReleases>
                <overWriteSnapshots>false</overWriteSnapshots>
                <overWriteIfNewer>true</overWriteIfNewer>
            </configuration>
        </execution>
    </executions>
</plugin>

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

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


Pau*_*ans 7

对于任何寻找从 \xc3\xbcber JAR 文件中排除特定依赖项的选项的人来说,这是一个适合我的解决方案:

\n
<project...>\n    <dependencies>\n        <dependency>\n            <groupId>org.apache.spark</groupId>\n            <artifactId>spark-core_2.11</artifactId>\n            <version>1.6.1</version>\n            <scope>provided</scope> <!--  <=============  -->\n        </dependency>\n    </dependencies>\n\n    <build>\n        <plugins>\n            <plugin>\n                <artifactId>maven-assembly-plugin</artifactId>\n                <configuration>\n                    <descriptorRefs>\n                        <descriptorRef>jar-with-dependencies</descriptorRef>\n                    </descriptorRefs>\n                    <archive>\n                        <manifest>\n                            <mainClass>...</mainClass>\n                        </manifest>\n                    </archive>\n                </configuration>\n                <executions>\n                    <execution>\n                        <id>make-assembly</id>\n                        <phase>package</phase>\n                        <goals>\n                            <goal>single</goal>\n                        </goals>\n                    </execution>\n                </executions>\n            </plugin>\n        </plugins>\n    </build>\n</project>\n
Run Code Online (Sandbox Code Playgroud)\n

它不是mvn- assembly-plugin的配置,而是依赖项的属性。

\n


fas*_*cja 6

对我有用的东西是:

  <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>
Run Code Online (Sandbox Code Playgroud)

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

<dependency>
  ..
  <scope>system</scope>
  <systemPath>${project.basedir}/lib/myjar.jar</systemPath>
</dependency>
Run Code Online (Sandbox Code Playgroud)

我已经更改了user189057 提供的代码:

  1. maven-dependency-plugin 在“准备包”阶段执行
  2. 我将解压的类直接提取到“目标/类”


Eli*_*iuX 6

这是我发现的最好的方法:

<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>
Run Code Online (Sandbox Code Playgroud)

通过此配置,所有依赖项将位于/dependency-jars. 我的应用程序没有Main类,只有上下文类,但我的依赖项之一确实有一个启动 JMX 服务器并接收一个或一个参数的Main类 ( ) 。这样我就可以像这样启动我的应用程序:com.myDomain.etc.MainClassNamestartstop

java -jar ./lib/TestApp-1.0-SNAPSHOT.jar start
Run Code Online (Sandbox Code Playgroud)


pra*_*upd 6

已经有数百万个答案。我想添加你不需要,<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>
Run Code Online (Sandbox Code Playgroud)

建造

  <build>
    <finalName>log-enrichment</finalName>
    <plugins>
      <plugin>
        <artifactId>maven-assembly-plugin</artifactId>
        <configuration>
          <descriptorRefs>
            <descriptorRef>jar-with-dependencies</descriptorRef>
          </descriptorRefs>
        </configuration>
      </plugin>
    </plugins>
  </build>
Run Code Online (Sandbox Code Playgroud)

核实

mvn clean compile assembly:single
Run Code Online (Sandbox Code Playgroud)


uwe*_*vil 6

我想将我的 Spring 应用程序(使用 Apereo Foundation 的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>
Run Code Online (Sandbox Code Playgroud)

开始课程是我的主要课程:

<properties>
    <java.version>1.8</java.version>
    <start-class>com.test.Application</start-class>
</properties>
Run Code Online (Sandbox Code Playgroud)

我的应用程序是:

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);
            }
        };
    }

}
Run Code Online (Sandbox Code Playgroud)


SRG*_*SRG 5

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

我看到了重点(易于部署/使用)但它取决于你的项目的用例(并且可能有替代方案(见下文)).

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

但是如果你在其他环境中使用你的项目(比如在webapp中,或者放在其他jar所在的文件夹中),你的类路径中可能会有jar副本(文件夹中的那些,jar中的那个).也许不是出价协议,但我通常会避免这种情况.

一个很好的选择:

  • 将您的应用程序部署为.zip/.war:存档包含项目的jar和所有相关的jar;
  • 使用动态类加载器机制(参见Spring,或者您可以轻松地自己完成),以获得项目的单个入口点(单个类开始 - 参见另一个答案的Manifest机制),它将(动态)添加到当前类路径所有其他需要的罐子.

像这样,最后只有一个清单和一个"特殊的动态类加载器主",你可以用以下内容启动你的项目:

java -jar ProjectMainJar.jar com.stackoverflow.projectName.MainDynamicClassLoaderClass
Run Code Online (Sandbox Code Playgroud)


小智 5

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

mvn assembly:assembly
Run Code Online (Sandbox Code Playgroud)

  • 我认为你仍然需要在 `pom.xml` 中做一些事情,否则你会得到 `Error reading assembly: No assembly descriptors found.`。无论如何,这就是我的情况。 (5认同)

Roc*_*nde 5

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

\n

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

\n
    \n
  1. 只需右键单击您的项目文件夹(在 Eclipse 中)并选择导出

    \n
  2. \n
  3. 然后选择Java \xe2\x86\x92 Runnable JAR

    \n
  4. \n
  5. 系统将要求您选择 JAR 文件的位置

    \n
  6. \n
  7. 最后,选择具有要运行的Main方法的类,然后选择 *使用 JAR 文件打包依赖项,然后单击完成

    \n
  8. \n
\n


sal*_*nbw 5

这也可能是一种选择。您将能够构建您的 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>
Run Code Online (Sandbox Code Playgroud)


Ano*_*Rai 5

为了解决此问题,我们将使用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>
Run Code Online (Sandbox Code Playgroud)

完成此操作后,请不要忘记使用以下命令运行MAVEN工具mvn clean compile assembly:single

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