如何使用 Maven 创建具有依赖项的可执行/可运行 JAR?
我想将我的项目打包在一个可执行 JAR 中以供分发。
如何使 Maven 项目将所有依赖 JAR 打包到我的输出 JAR 中?
I want to package my project in a single executable JAR for distribution.
How can I make a Maven project package all dependency JARs into my output JAR?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(30)
并且您运行它时
应该在 assembly:single 之前添加编译目标,否则不包含您自己项目上的代码。
请参阅注释中的更多详细信息。
通常,此目标与自动执行的构建阶段相关联。 这可确保在执行 mvn install 或执行部署/发布时构建 JAR。
and you run it with
Compile goal should be added before assembly:single or otherwise the code on your own project is not included.
See more details in comments.
Commonly this goal is tied to a build phase to execute automatically. This ensures the JAR is built when executing
mvn install
or performing a deployment/release.您可以使用依赖插件在打包阶段之前在单独的目录中生成所有依赖项,然后将其包含在清单的类路径中:
或者,使用 ${project.build.directory}/classes/lib${project.build.directory}/classes/lib code> 作为 OutputDirectory 将所有 JAR 文件集成到主 JAR 文件中,但随后您将需要添加自定义类加载代码来加载 JAR 文件。
You can use the dependency-plugin to generate all dependencies in a separate directory before the package phase and then include that in the classpath of the manifest:
Alternatively, use
${project.build.directory}/classes/lib
as OutputDirectory to integrate all JAR files into the main JAR file, but then you will need to add custom classloading code to load the JAR files.(GitHub)
注释
请参阅 executable-jar-with-maven- example Stephan 提供了优缺点。
对于手动部署
将依赖项复制到特定目录
使 JAR 文件可执行并可识别类路径
此时,JAR 文件实际上可以使用外部类路径元素执行。
制作可部署的存档
JAR 文件只能通过同级
...lib/
目录执行。 我们需要制作存档以与目录及其内容一起部署。现在您有了
target/${project.build.finalName}.(zip|tar|tar.bz2|tar.gz)
,其中每个都包含jar
和lib/*
.Apache Maven 组装插件
您有
target/${project.bulid.finalName}-jar-with-dependency.jar
。Apache Maven Shade 插件
您有
target/${project.build.finalName}-shaded.jar
。onejar-maven-plugin
Spring Boot Maven 插件
您有
target/${project.bulid.finalName}-spring-boot.jar
。Quarkus Maven 插件
您有 target/${project.bulid.finalName}-quarkus.jar。
See executable-jar-with-maven-example (GitHub)
Notes
Those pros and cons are provided by Stephan.
For Manual Deployment
Copy Dependencies to a specific directory
Make the JAR File Executable and Classpath Aware
At this point the JAR file is actually executable with external classpath elements.
Make Deployable Archives
The JAR file is only executable with the sibling
...lib/
directory. We need to make archives to deploy with the directory and its content.Now you have
target/${project.build.finalName}.(zip|tar|tar.bz2|tar.gz)
which each contains thejar
andlib/*
.Apache Maven Assembly Plugin
You have
target/${project.bulid.finalName}-jar-with-dependencies.jar
.Apache Maven Shade Plugin
You have
target/${project.build.finalName}-shaded.jar
.onejar-maven-plugin
Spring Boot Maven Plugin
You have
target/${project.bulid.finalName}-spring-boot.jar
.Quarkus Maven Plugin
You have target/${project.bulid.finalName}-quarkus.jar.
采用IAdapter的答案 并重新格式化它,我们有:
接下来,我建议将其作为构建的自然部分,而不是显式调用的东西。 要使其成为构建不可或缺的一部分,请将此插件添加到您的 pom.xml 并将其绑定到 package 生命周期事件。 然而,一个问题是,如果将其放入 pom.xml 中,则需要调用“ assembly:single ”目标,而如果从命令行手动执行它,则需要调用“ assembly: assembly”。
Taking IAdapter's answer and reformatting it, we have:
Next, I would recommend making this a natural part of your build, rather than something to call explicitly. To make this a integral part of your build, add this plugin to your
pom.xml
and bind it to thepackage
lifecycle event. However, a gotcha is that you need to call theassembly:single
goal if putting this in your pom.xml, while you would call 'assembly:assembly' if executing it manually from the command line.使用maven-shade-plugin将所有依赖项打包到一个 über-JAR 文件中。 它还可用于通过指定主类来构建可执行 JAR 文件。 在尝试使用maven-assemble和maven-jar之后,我发现这个插件最适合我的需求。
我发现这个插件特别有用,因为它合并特定文件的内容而不是覆盖它们。 当 JAR 文件中存在具有相同名称的资源文件并且插件尝试打包所有资源文件时,需要执行此操作。
请参阅下面的示例:
Use the maven-shade-plugin to package all dependencies into one über-JAR file. It can also be used to build an executable JAR file by specifying the main class. After trying to use maven-assembly and maven-jar, I found that this plugin best suited my needs.
I found this plugin particularly useful as it merges the content of specific files instead of overwriting them. This is needed when there are resource files that are have the same name across the JAR files and the plugin tries to package all the resource files.
See the example below:
您可以使用 maven-shade 插件构建 über JAR 文件,如下所示:
You can use the maven-shade plugin to build an über JAR file like below:
我长期使用 Maven 程序集插件,但我找不到
“已添加,正在跳过”
。 现在,我正在使用另一个插件 - onejar-maven-plugin。 下面是一个示例(mvn package
构建 JAR 文件):您需要为该插件添加一个存储库:
I have long used the Maven assembly plugin, but I could not find a solution to the problem with
"already added, skipping"
. Now, I'm using another plugin - onejar-maven-plugin. An example is below (mvn package
builds the JAR file):You need to add a repository for that plugin:
您可以将以下内容添加到您的 pom.xml 文件中:
然后,您必须通过控制台切换到 pom.xml 文件所在的目录。 然后你必须执行mvn assembly:single,然后你的带有依赖项的可执行JAR文件将有望被构建。 您可以在使用 cd ./target 切换到输出(目标)目录并使用类似于 java -jar mavenproject1-1.0-SNAPSHOT-jar-with- 的命令启动 JAR 时检查它。依赖项.jar。
我使用 Apache Maven 3.0.3 对此进行了测试。
You can add the following to your pom.xml file:
Afterwards you have to switch via the console to the directory, where the pom.xml file is located. Then you have to execute mvn assembly:single and then your executable JAR file with dependencies will be hopefully build. You can check it when switching to the output (target) directory with cd ./target and starting your JAR with a command similar to java -jar mavenproject1-1.0-SNAPSHOT-jar-with-dependencies.jar.
I tested this with Apache Maven 3.0.3.
我仔细检查了每一个响应,希望制作一个包含所有依赖项的可执行 JAR 文件,但没有一个能正常工作。 答案是阴影插件,它非常简单明了。
请注意,您的依赖项需要具有编译或运行时的范围才能正常工作。
此示例来自 mkyong.com
I went through every one of these responses looking to make a fat executable JAR file containing all dependencies and none of them worked right. The answer is the shade plugin, it’s very easy and straightforward.
Be aware that your dependencies need to have a scope of compile or runtime for this to work properly.
This example came from mkyong.com
您可以使用 maven-dependency-plugin,但问题是如何创建可执行 JAR 文件。 为此,需要对 Matthew Franglen 的回应(顺便说一句,从干净的目标开始时,使用依赖插件需要更长的时间来构建):
You can use maven-dependency-plugin, but the question was how to create an executable JAR file. To do that requires the following alteration to Matthew Franglen's response (btw, using the dependency plugin takes longer to build when starting from a clean target):
如果您确实想将其他 JAR 内容重新打包到单个生成的 JAR 中,则另一个选择是 Maven组装插件。 它解压所有内容,然后通过
true
将所有内容重新打包到目录中。 然后您将进行第二遍将其构建到一个巨大的 JAR 中。另一个选项是 OneJar 插件。 这一步即可执行上述所有重新打包操作。
Another option if you really want to repackage the other JARs contents inside your single resultant JAR is the Maven Assembly plugin. It unpacks and then repacks everything into a directory via
<unpack>true</unpack>
. Then you'd have a second pass that built it into one massive JAR.Another option is the OneJar plugin. This performs the above repackaging actions all in one step.
您可以结合使用
maven-shade-plugin
和maven-jar-plugin
。maven-shade-plugin
将您的类和所有依赖项打包在一个 JAR 文件中。maven-jar-plugin
以指定可执行 JAR 文件的主类(请参阅 设置类路径,“使 Jar 可执行”一章)。maven-jar-plugin
的 POM 配置示例:最后通过调用以下命令创建可执行 JAR 文件:
You could combine the
maven-shade-plugin
andmaven-jar-plugin
.maven-shade-plugin
packs your classes and all dependencies in a single JAR file.maven-jar-plugin
to specify the main class of your executable JAR file (see Set Up The Classpath, chapter "Make The Jar Executable").Example POM configuration for
maven-jar-plugin
:Finally create the executable JAR file by invoking:
它的工作方式如下:
解包必须在生成资源阶段,否则不会作为资源包含在内。
It will work like:
Unpacking has to be in the generate-resources phase or it will not be included as resources.
我认为刘肯说得对。 Maven 依赖插件允许您扩展所有依赖项,然后您可以将其视为资源。 这允许您将它们包含在主要工件中。 使用程序集插件会创建一个难以修改的辅助工件 - 在我的例子中,我想添加自定义清单条目。 我的 POM 文件最终为:
Ken Liu has it right in my opinion. The Maven dependency plugin allows you to expand all the dependencies, which you can then treat as resources. This allows you to include them in the main artifact. The use of the assembly plugin creates a secondary artifact which can be difficult to modify - in my case I wanted to add custom manifest entries. My POM file ended up as:
为了解决这个问题,我们将使用 Maven Assembly 插件,它将 JAR 文件及其依赖项 JAR 文件创建为单个可执行 JAR 文件。 只需在您的 pom.xml 文件中添加以下插件配置即可。
执行此操作后,不要忘记使用以下命令运行 Maven 工具:
Maven - 将 JAR 文件及其依赖项 JAR 文件创建为单个可执行 JAR 文件
To resolve this issue, we will use the Maven Assembly plugin that will create the JAR file together with its dependency JAR files into a single executable JAR file. Just add the below plugin configuration in your pom.xml file.
After doing this, don’t forget to run the Maven tool with this command:
Maven - Creating a JAR file together with its dependency JAR files into a single executable JAR file
使用 maven- assembly-plugin-2.2.1 定位共享程序集文件有什么问题?
尝试使用descriptorId配置参数而不是descriptor/descriptor或descriptorRefs/descriptorRef参数。
他们都没有做你需要的事情:在类路径上查找文件。
当然,您需要将共享程序集所在的包添加到 maven- assembly-plugin 的类路径上(见下文)。
如果您使用的是 Maven 2.x(不是 Maven 3.x),则可能需要在pluginManagement 部分的最顶层父 pom.xml 中添加此依赖项。
有关更多信息,请参阅此细节。
类:org.apache.maven.plugin. assembly.io.DefaultAssemblyReader
示例:
What is the problem with locating shared assembly files with maven-assembly-plugin-2.2.1?
Try using the descriptorId configuration parameter instead of descriptors/descriptor or descriptorRefs/descriptorRef parameters.
Neither of them do what you need: look for the file on classpath.
Of course you need adding the package where the shared assembly resides on the maven-assembly-plugin's classpath (see below).
If you're using Maven 2.x (not Maven 3.x), you may need adding this dependency in top-most parent pom.xml in the pluginManagement section.
See this for more details.
Class: org.apache.maven.plugin.assembly.io.DefaultAssemblyReader
Example:
我比较了这篇文章中提到的树插件。 我生成了两个 JAR 文件和一个包含所有 JAR 文件的目录。 我比较了结果,绝对是 maven-shade-plugin 是最好的。
我的挑战是我有多个需要合并的 Spring 资源以及 jax- rs 和 JDBC 服务。 与maven-assemble-plugin相比,它们都被shade插件正确合并了。 在这种情况下,除非您将它们复制到您自己的资源文件夹中并手动合并一次,否则 Spring 将失败。
两个插件都输出正确的依赖树。 我有多个范围,如测试、提供、编译等。两个插件都跳过了测试和提供。 他们都生成了相同的清单,但我能够使用他们的变压器将许可证与阴影插件合并。
使用maven-dependency-plugin当然不会遇到这些问题,因为 JAR 文件不会被提取。 但正如其他人指出的那样,您需要携带一个额外的文件才能正常工作。
以下是 pom.xml 文件的片段:
I compared the tree plugins mentioned in this post. I generated two JAR files and a directory with all the JAR files. I compared the results and definitely the maven-shade-plugin is the best.
My challenge was that I have multiple Spring resources that needed to be merged, as well as jax-rs, and JDBC services. They were all merged properly by the shade plugin in comparison with the maven-assembly-plugin. In which case Spring will fail unless you copy them to your own resources folder and merge them manually one time.
Both plugins output the correct dependency tree. I had multiple scopes like test, provide, compile, etc. The test and provided were skipped by both plugins. They both produced the same manifest, but I was able to consolidate licenses with the shade plugin using their transformer.
With the maven-dependency-plugin of course you don't have those problems, because the JAR files are not extracted. But like some other have pointed out, you need to carry one extra file(s) to work properly.
Here is a snip of the pom.xml file:
对于任何寻找从 uber JAR 文件中排除特定依赖项的选项的人来说,这是一个适合我的解决方案:
它不是 mvn- assembly-plugin 的配置,而是依赖项的属性。
For anyone looking for options to exclude specific dependencies from the über JAR file, this is a solution that worked for me:
It's not a configuration of the mvn-assembly-plugin, but a property of the dependency.
将所有依赖项嵌入到项目的 JAR 文件本身中可能不是一个好主意。
我明白这一点(易于部署/使用),但这取决于您项目的用例(并且可能有替代方案(见下文))。
如果您完全独立使用它,为什么不呢?
但是,如果您在其他上下文中使用您的项目(例如在 Web 应用程序中,或者放入其他 JAR 所在的文件夹中),则您的类路径中可能会有 JAR 重复项(文件夹中的 JAR、JAR 文件中的 JAR) 。 也许不是投标交易,但我通常会避免这种情况。
一个不错的选择:
像这样,最后只有一个清单和一个“特殊动态类加载器主”,您可以通过以下方式启动您的项目:
It may not be a good idea to embed all the dependencies in the project's JAR file itself.
I see the point (ease of deployment / usage), but it depends of the use case of your project (and there may be alternatives (see below)).
If you use it fully standalone, why not?
But if you use your project in other contexts (like in a web application, or dropped in a folder where other JARs are sitting), you may have JAR duplicates in your classpath (the ones in the folder, the one in the JAR files). Maybe not a bid deal, but I usually avoid this.
A good alternative:
Like this, with in the end just a manifest and a "special dynamic classloader main", you can start your project with:
对我有用的是:
我遇到了一个特殊的情况,因为我的依赖是系统一:
我更改了代码 由 user189057 提供 进行更改:
Something that has worked for me was:
I had an extraordinary case, because my dependency was system one:
I have changed the code provided by user189057 with changes:
这是我发现的最好方法:
使用此配置,所有依赖项将位于
/dependency-jars
中。 我的应用程序没有Main
类,只有上下文类,但我的依赖项之一确实有一个Main
类(com.myDomain.etc.MainClassName
)启动 JMX 服务器,并接收start
或stop
参数。 这样我就可以像这样启动我的应用程序:This is the best way I found:
With this configuration, all dependencies will be located in
/dependency-jars
. My application has noMain
class, just context ones, but one of my dependencies do have aMain
class (com.myDomain.etc.MainClassName
) that starts the JMX server, and receives astart
or astop
parameter. So with this I was able to start my application like this:已经有数百万个答案。 我想补充一点,如果您不需要向应用程序添加entryPoint,则不需要
。 例如,API 可能不一定有main
方法。Maven 插件配置
构建
验证
There are millions of answers already. I wanted to add you don't need
<mainClass>
if you don't need to add entryPoint to your application. For example, APIs may not have necessarily have amain
method.Maven plugin configuration
Build
Verify
我想将我的 Spring 应用程序(使用 Apereo Foundation 的 CAS 客户端)迁移到 Spring Boot 1.5 。 我遇到了很多问题,例如:
我尝试制作一个具有所有依赖项的唯一 JAR 文件。 在互联网上搜索后,我能够用以下几行来做到这一点:
start-class是我的主类:
而我的Application是:
I wanted to migrate my Spring application (using Apereo Foundation's CAS client) to Spring Boot 1.5. I ran into many problems, like:
I tried to make one unique JAR file with all dependencies. After searching on the Internet, I was able to do it with these lines:
start-class is my main class:
And my Application is:
要从命令行本身创建可执行 JAR,只需从项目路径运行以下命令:
To create an executable JAR from the command line itself, just run the below command from the project path:
我在这里尝试了最受支持的答案,并且能够使 JAR 文件可运行。 但程序没有正确运行。 我不知道是什么原因。 当我尝试从 Eclipse 运行时,我得到了不同的结果,但是当我从命令行运行 JAR 文件,得到了不同的结果(它因程序特定的运行时错误而崩溃)。
我有一个与 OP 类似的要求,只是我的项目有太多(Maven)依赖项。 幸运的是,唯一对我有用的解决方案是使用 Eclipse。 它非常简单,也非常直接。 这不是 OP 的解决方案,但它是为具有类似需求但具有许多 Maven 依赖项的人提供的解决方案,
只需右键单击项目文件夹(在 Eclipse 中)并选择导出< /em>
然后选择Java → Runnable JAR
系统将要求您选择 JAR 文件的位置
最后,选择具有要运行的 Main 方法的类,然后选择 *Package dependency with the JAR file 并单击 >完成
I tried the most upvoted answer here and was able to get the JAR file runnable. But the program didn't run correctly. I do not know what the reason was. When I try to run from Eclipse, I get a different result, but when I run the JAR file from command line I get a different result (it crashes with a program-specific runtime error).
I had a similar requirement as the OP just that I had too many (Maven) dependencies for my project. Fortunately, the only solution that worked for me was that using Eclipse. It is very simple and very straightforward. This is not a solution for the OP, but it is a solution for someone who has a similar requirement, but with many Maven dependencies,
Just right-click on your project folder (in Eclipse) and select Export
Then select Java → Runnable JAR
You will be asked to choose the location of the JAR file
Finally, select the class that has the Main method that you want to run and choose *Package dependencies with the JAR file and click Finish
这也可能是一种选择。 您将能够构建您的 JAR 文件。
This could also be an option. You will be able to build your JAR file.
添加到文件 pom.xml:
就是
这样。 接下来,mvn 包还将另外创建一个 fat JAR,包括所有依赖 JAR 文件。
Add to file pom.xml:
And
That’s it. Next, the mvn package will also create one fat JAR additionally, including all dependency JAR files.
maven-assemble-plugin 对我来说非常有用。
我花了几个小时使用 maven-dependency-plugin,但无法让它工作。 主要原因是我必须在配置部分中显式定义工件项,应将其包含在内,如 文档。
当您想要使用它时,有一个示例:
mvn dependency:copy
,其中不包含任何artifactItems,但它不起作用。The maven-assembly-plugin worked great for me.
I spent hours with the maven-dependency-plugin and couldn't make it work. The main reason was that I had to define the artifact items explicitly in the configuration section which should be included as it is described in the documentation.
There is an example there for the cases when you want to use it like:
mvn dependency:copy
, where there are not included any artifactItems, but it doesn't work.我尝试了多种解决方案,但在我们想要创建一个不可执行的胖 JAR 文件的情况下,这是一个完美的解决方案,其中包含与先前没有相关性的外部系统的所有内部依赖项。 测试了生产场景。
将其包含在 pom.xml 文件中:
构建 fat JAR 文件所需运行的命令:
I tried multiple solutions, but this is the one that worked perfectly in the scenario where we wanted to create a non-executable fat JAR file with all internal dependencies for external systems having no previous relevance. A production scenario was tested.
Include this in the pom.xml file:
The command to run to build the fat JAR file:
这篇博文展示了另一种结合 maven-jar 和 maven-assemble 插件的方法。 使用博客文章中的程序集配置 XML 文件,还可以控制是否扩展依赖项或仅将其收集在文件夹中并由清单中的类路径条目引用:
确切地说,这里描述的是:使用 Maven 的具有依赖 JAR 文件的可执行 JAR 文件
This blog post shows another approach with combining the maven-jar and maven-assembly plugins. With the assembly configuration XML file from the blog post it can also be controlled if dependencies will be expanded or just be collected in a folder and referenced by a classpath entry in the manifest:
And exactly that one is described here: Executable JAR file with dependent JAR files using Maven