How to Create an Executable JAR with Maven – 如何用Maven创建一个可执行的JAR

最后修改: 2016年 10月 20日

中文/混合/英文(键盘快捷键:t)

1. Overview

1.概述

In this quick tutorial, we’ll focus on packaging a Maven project into an executable Jar file.

在这个快速教程中,我们将重点介绍将Maven项目打包成可执行的Jar文件。

When creating a jar file, we usually want to run it easily, without using the IDE. To that end, we’ll discuss the configuration and pros/cons of using each of these approaches for creating the executable.

当创建一个jar文件时,我们通常希望不使用IDE就能轻松地运行它。为此,我们将讨论使用这些方法中的每一种来创建可执行文件的配置和利/弊。

2. Configuration

2.配置

We don’t need any additional dependencies to create an executable jar. We just need to create a Maven Java project and have at least one class with the main(…) method.

我们不需要任何额外的依赖来创建一个可执行的jar。我们只需创建一个Maven Java项目,并至少有一个带有main(..)方法的类。

In our example, we created Java class named ExecutableMavenJar.

在我们的例子中,我们创建了名为ExecutableMavenJar的Java类。

We also need to make sure that our pom.xml contains these elements:

我们还需要确保我们的pom.xml包含这些元素。

<modelVersion>4.0.0</modelVersion>
<groupId>com.baeldung</groupId>
<artifactId>core-java</artifactId>
<version>0.1.0-SNAPSHOT</version>
<packaging>jar</packaging>

The most important aspect here is the type — to create an executable jar, double-check the configuration uses a jar type.

这里最重要的是类型–要创建一个可执行的jar,仔细检查配置是否使用了jar类型。

Now we can start using the various solutions.

现在我们可以开始使用各种解决方案。

2.1. Manual Configuration

2.1.手动配置

Let’s start with a manual approach with the help of the maven-dependency-plugin.

让我们先在maven-dependency-plugin的帮助下采用手动方法。

We’ll begin by copying all required dependencies into the folder that we’ll specify:

我们将首先把所有需要的依赖项复制到我们将指定的文件夹中。

<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}/libs
                </outputDirectory>
            </configuration>
        </execution>
    </executions>
</plugin>

There are two important aspects to notice.

有两个重要方面需要注意。

First, we specify the goal copy-dependencies, which tells Maven to copy these dependencies into the specified outputDirectory. In our case, we’ll create a folder named libs inside the project build directory (which is usually the target folder).

首先,我们指定目标copy-dependencies,它告诉Maven将这些依赖项复制到指定的outputDirectory。在我们的例子中,我们将在项目构建目录(通常是target文件夹)内创建一个名为libs的文件夹。

Second, we are going to create executable and classpath-aware jar, with the link to the dependencies copied in the first step:

第二,我们要创建可执行的和可识别classpath的jar,并将其链接到第一步中复制的依赖项。

<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-jar-plugin</artifactId>
    <configuration>
        <archive>
            <manifest>
                <addClasspath>true</addClasspath>
                <classpathPrefix>libs/</classpathPrefix>
                <mainClass>
                    com.baeldung.executable.ExecutableMavenJar
                </mainClass>
            </manifest>
        </archive>
    </configuration>
</plugin>

The most important part of this is the manifest configuration. We add a classpath, with all dependencies (folder libs/), and provide the information about the main class.

这其中最重要的部分是manifest配置。我们添加一个classpath,包括所有的依赖项(文件夹libs/),并提供关于主类的信息。

Please note that we need to provide a fully qualified name of the class, which means it will include package name.

请注意,我们需要提供一个完全合格的类名,这意味着它将包括包名。

The advantages and disadvantages of this approach are:

这种方法的优点和缺点是。

  • pros – transparent process, where we can specify each step
  • cons – manual; dependencies are out of the final jar, which means that our executable jar will only run if the libs folder will be accessible and visible for a jar

2.2. Apache Maven Assembly Plugin

2.2.Apache Maven Assembly Plugin

The Apache Maven Assembly Plugin allows users to aggregate the project output along with its dependencies, modules, site documentation, and other files into a single, runnable package.

Apache Maven汇编插件允许用户将项目输出及其依赖关系、模块、网站文档和其他文件汇总到一个可运行的软件包中。

The main goal in the assembly plugin is the single goal, which is used to create all assemblies (all other goals are deprecated and will be removed in a future release).

集合体插件中的主要目标是single目标,它被用来创建所有的集合体(所有其他的目标都已废弃,将在未来的版本中被删除)。

Let’s take a look at the configuration in pom.xml:

让我们看一下pom.xml中的配置。

<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>
                        com.baeldung.executable.ExecutableMavenJar
                    </mainClass>
                </manifest>
                </archive>
                <descriptorRefs>
                    <descriptorRef>jar-with-dependencies</descriptorRef>
                </descriptorRefs>
            </configuration>
        </execution>
    </executions>
</plugin>

Similarly to the manual approach, we need to provide the information about the main class. The difference is that the Maven Assembly Plugin will automatically copy all required dependencies into a jar file.

与手动方法类似,我们需要提供主类的相关信息。不同的是,Maven汇编插件会自动将所有需要的依赖项复制到jar文件中。

In the descriptorRefs part of the configuration code, we provided the name that will be added to the project name.

在配置代码的descriptorRefs部分,我们提供了将被添加到项目名称中的名称。

Output in our example will be named as core-java-jar-with-dependencies.jar.

在我们的例子中,输出将被命名为core-java-jar-with-dependencies.jar

  • pros – dependencies inside the jar file, one file only
  • cons – basic control of packaging our artifact, for example, there is no class relocation support

2.3. Apache Maven Shade Plugin

2.3.Apache Maven Shade Plugin

Apache Maven Shade Plugin provides the capability to package the artifact in an uber-jar, which consists of all dependencies required to run the project. Moreover, it supports shading — i.e. renaming — the packages of some of the dependencies.

Apache Maven Shade Plugin提供了将工件打包成uber-jar的能力,其中包括运行项目所需的所有依赖项。此外,它还支持对某些依赖项的包进行着色–即重命名。

Let’s take a look at the configuration:

让我们看一下配置。

<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>com.baeldung.executable.ExecutableMavenJar</mainClass>
                </transformer>
            </transformers>
        </configuration>
        </execution>
    </executions>
</plugin>

There are three main parts to this configuration.

这个配置有三个主要部分。

First, <shadedArtifactAttached> marks all dependencies to be packaged into the jar.

首先,<shadedArtifactAttached>标记所有要打包到jar的依赖。

Second, we need to specify the transformer implementation; we used the standard one in our example.

第二,我们需要指定变换器的实现;在我们的例子中我们使用了标准的变换器。

Finally, we need to specify the main class of our application.

最后,我们需要指定我们应用程序的主类。

The output file will be named core-java-0.1.0-SNAPSHOT-shaded.jar, where core-java is our project name followed by snapshot version and plugin name.

输出文件将被命名为core-java-0.1.0-SNAPSHOT-shaded.jar,其中core-java是我们的项目名称,后面是快照版本和插件名称。

  • pros – dependencies inside the jar file, advanced control of packaging our artifact, with shading and class relocation
  • cons – complex configuration (especially if we want to use advanced features)

2.4. One Jar Maven Plugin

2.4.One Jar Maven Plugin

Another option to create an executable jar is the One Jar project.

创建可执行jar的另一个选择是One Jar项目。

This provides a custom class loader that knows how to load classes and resources from jars inside an archive, instead of from jars in the filesystem.

这提供了一个自定义的类加载器,它知道如何从归档的jars中加载类和资源,而不是从文件系统中的jars

Let’s take a look at the configuration:

让我们看一下配置。

<plugin>
    <groupId>com.jolira</groupId>
    <artifactId>onejar-maven-plugin</artifactId>
    <executions>
        <execution>
            <configuration>
                <mainClass>org.baeldung.executable.
                  ExecutableMavenJar</mainClass>
                <attachToBuild>true</attachToBuild>
                <filename>
                  ${project.build.finalName}.${project.packaging}
                </filename>
            </configuration>
            <goals>
                <goal>one-jar</goal>
            </goals>
        </execution>
    </executions>
</plugin>

As shown in the configuration, we need to specify the main class and attach all dependencies to build, by using attachToBuild = true.

如配置中所示,我们需要指定主类,并通过使用attachToBuild = true,将所有的依赖项附加到构建中。

Also, we should provide the output filename. Moreover, the goal for Maven is one-jar. Please note that One Jar is a commercial solution that will make dependency jars not expanded into the filesystem at runtime.

此外,我们还应该提供输出文件名。此外,Maven的目标是one-jar。请注意,One Jar是一个商业解决方案,它将使依赖性jars在运行时不扩展到文件系统中。

  • pros – clean delegation model, allows classes to be at the top level of the One Jar, supports external jars and can support Native libraries
  • cons – not actively supported since 2012

2.5. Spring Boot Maven Plugin

2.5.Spring Boot Maven Plugin

Finally, the last solution we’ll look at is the Spring Boot Maven Plugin.

最后,我们要看的最后一个解决方案是Spring Boot Maven Plugin。

This allows for packaging executable jar or war archives and run an application “in place.”

这允许打包可执行的jarwar档案并 “就地 “运行一个应用程序。

To use it, we need to use at least Maven version 3.2. The detailed description is available here.

要使用它,我们至少需要使用Maven 3.2版本。详细说明请见这里

Let’s have a look at the config:

让我们看一下配置。

<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>
                  com.baeldung.executable.ExecutableMavenJar
                </mainClass>
            </configuration>
        </execution>
    </executions>
</plugin>

There are two differences between Spring plugin and the others: The goal of the execution is called repackage, and the classifier is named spring-boot.

Spring插件和其他的插件有两个不同之处。执行的目标被称为repackage,分类器被称为spring-boot

Note that we don’t need to have Spring Boot application in order to use this plugin.

请注意,我们不需要有Spring Boot应用程序就可以使用这个插件。

  • pros – dependencies inside a jar file, we can run it in every accessible location, advanced control of packaging our artifact, with excluding dependencies from the jar file etc., packaging of war files as well
  • cons – adds potentially unnecessary Spring and Spring Boot-related classes

2.6. Web Application With Executable Tomcat

2.6.使用可执行的Tomcat的Web应用程序

In the last part, we want to cover a standalone web application that is packed inside a jar file.

在最后一部分,我们要介绍一个独立的网络应用,它被包装在一个jar文件内。

In order to do that, we need to use different plugin, designed for creating executable jar files:

为了做到这一点,我们需要使用不同的插件,专门用于创建可执行的jar文件。

<plugin>
    <groupId>org.apache.tomcat.maven</groupId>
    <artifactId>tomcat7-maven-plugin</artifactId>
    <version>2.0</version>
    <executions>
        <execution>
            <id>tomcat-run</id>
            <goals>
                <goal>exec-war-only</goal>
            </goals>
            <phase>package</phase>
            <configuration>
                <path>/</path>
                <enableNaming>false</enableNaming>
                <finalName>webapp.jar</finalName>
                <charset>utf-8</charset>
            </configuration>
        </execution>
    </executions>
</plugin>

The goal is set as exec-war-only, path to our server is specified inside configuration tag, with additional properties, like finalName, charset etc.

目标被设置为exec-war-only路径到我们的服务器被指定在configurationtag里面,还有其他属性,比如finalName,charset等等。

To build a jar, we run man package, which will result in creating webapp.jar in our target directory.

为了构建一个jar,我们运行man package,这将导致在我们的target目录下创建webapp.jar

To run the application, we just write java -jar target/webapp.jar in our console and try to test it by specifying the localhost:8080/ in a browser.

要运行该应用程序,我们只需在控制台中写下 java -jar target/webapp.jar ,并通过在浏览器中指定localhost:8080/来尝试测试它。

  • pros – having one file, easy to deploy and run
  • cons – a size of the file is much larger, due to packing Tomcat embedded distribution inside a war file

Note that this is the latest version of this plugin, which supports Tomcat7 server. To avoid errors, we can check that our dependency for Servlets has scope set as provided, otherwise, there will be a conflict at the runtime of executable jar:

注意,这是该插件的最新版本,它支持Tomcat7服务器。为了避免错误,我们可以检查我们对Servlets的依赖是否已将scope设置为provided,否则,在可执行jarruntime会有冲突。

<dependency>
    <groupId>javax.servlet</groupId>
    <artifactId>javax.servlet-api</artifactId>
    <scope>provided</scope>
</dependency>

3. Conclusion

3.结论

In this article, we described many ways of creating an executable jar with various Maven plugins.

在这篇文章中,我们介绍了用各种Maven插件创建可执行jar的许多方法。

The full implementation of this tutorial can be found in these GitHub projects: executable jar and executable war.

本教程的完整实现可以在这些GitHub项目中找到。可执行的jar可执行的war

How to test? In order to compile the project into an executable jar, please run Maven with mvn clean package command.

如何测试?为了将项目编译成可执行的jar,请用mvn clean package命令运行Maven。

This article hopefully provided some more insights and will help you find your preferred approach depending on your needs.

这篇文章希望能提供一些更多的见解,并将帮助你根据你的需要找到你的首选方法。

One quick final note: We want to make sure the licenses of the jars we’re bundling don’t prohibit this kind of operation. That generally won’t be the case, but it’s worth considering.

最后一点:我们要确保我们所捆绑的罐子的许可证不禁止这种操作。一般来说,不会出现这种情况,但这值得考虑。