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

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


当前回答

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

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

请参见以下示例:

<plugins>
    <!-- This plugin provides the capability to package
         the artifact in an über-JAR file, 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 JAR files-->
                        <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>

其他回答

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

Maven可以编译所有的依赖项和插件。不是NetBeans。(如果您可以获得NetBeans并能够使用java.jar来实现这一点,请告诉我如何(^.^)v)

已解决-针对Linux:通过打开终端。

Then

cd /MyRootDirectoryForMyProject

Next

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

Next

mvn install

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

MyJarFile-1.0-jar-with-dependencies.jar

Now

cd target

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

最后

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

请参阅LifecyclePhaseNotFoundException。

maven汇编插件对我很有用。

我花了几个小时使用maven依赖插件,但无法使其工作。主要原因是我必须在配置部分中明确定义工件项,如文档中所述,应包含这些工件项。

这里有一个例子,当您想使用它时,比如:mvn dependency:copy,其中没有包含任何artifactItems,但它不起作用。

我仔细阅读了这些响应中的每一个,希望创建一个包含所有依赖项的可执行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

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

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

参见maven示例的可执行jar(GitHub)

笔记

这些利弊由Stephan提供。


用于手动部署

赞成的意见欺骗依赖项已从最终jar中删除。

将依赖项复制到特定目录

<plugin>
  <groupId>org.apache.maven.plugins</groupId>
  <artifactId>maven-dependency-plugin</artifactId>
  <executions>
    <execution>
      <id>copy-dependencies</id>
      <phase>prepare-package</phase>
      <goals>
        <goal>copy-dependencies</goal>
      </goals>
      <configuration>
        <outputDirectory>${project.build.directory}/${project.build.finalName}.lib</outputDirectory>
      </configuration>
    </execution>
  </executions>
</plugin>

使JAR文件可执行并支持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文件实际上可以通过外部类路径元素执行。

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),每个文件都包含jar和lib/*。


Apache Maven程序集插件

赞成的意见欺骗不支持类重新定位(如果需要类重新定位,请使用maven shade插件)。

<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.build.finalName}-jar-with-dependences.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插件

赞成的意见欺骗自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.build.finalName}-spring-boot.jar。