如何使用 Maven 创建具有依赖关系的可执行 JAR?
Posted
技术标签:
【中文标题】如何使用 Maven 创建具有依赖关系的可执行 JAR?【英文标题】:How can I create an executable JAR with dependencies using Maven? 【发布时间】:2010-10-09 03:27:17 【问题描述】:我想将我的项目打包到单个可执行 JAR 中以进行分发。
如何让一个 Maven 项目将所有依赖 JAR 打包到我的输出 JAR 中?
【问题讨论】:
请说明您所指的依赖插件的目标。我知道没有任何目标可以满足原始问题的要求:将所有依赖项 A)通过重新打包放入作者 jar 中,或 B)制作一个可执行 jar,该 jar 在 MANIFEST.MF 的类路径中包含其他依赖项 您可能会发现这很有用rationaljava.com/2015/02/… 2 个例子:tugay.biz/2015/12/a-standalone-java-web-application-with.htmltugay.biz/2016/11/how-did-i-create-executable-jar-with.html 参考***.com/questions/35217128/… 【参考方案1】:<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>
然后你运行它
mvn clean compile assembly:single
编译目标应该在汇编之前添加:single否则不包含你自己项目上的代码。
在 cmets 中查看更多详细信息。
通常,此目标与自动执行的构建阶段相关联。这可确保在执行 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>
【讨论】:
感谢@IAdapter。请注意,您应该始终事先进行编译,因为它只会将“目标/类”中的任何内容放入 JAR 中。这将确保 JAR 包含您最近对源代码所做的任何更改。所以,你应该这样做:mvn clean compile assembly:single
.
我看到这并没有将 jars 添加到 uber jar 中,而是将所有类文件添加到 jar 中。
提示:您也可以在configuration
中添加元素<appendAssemblyId>false</appendAssemblyId>
以避免名称中烦人的“-jar-with-dependencies”后缀
如果我没有 main 方法或类怎么办,我只需要一些随机的 java 文件作为 jar?
@user10201743 只是提供一点上下文:Maven 中的 Everything 是一个插件。编译器? maven-compiler-plugin
。测试? maven-surefire-plugin
。这两个,包括程序集,是官方的 maven 插件,所以它们也可以被视为 maven 的一部分(尤其是因为,至少现在,它们三个都默认在你的有效 POM 中)。【参考方案2】:
接受未回答的答案并重新格式化,我们有:
<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>
接下来,我建议将其作为构建的自然部分,而不是显式调用。要使其成为您构建的一个组成部分,请将此插件添加到您的 pom.xml
并将其绑定到 package
生命周期事件。但是,一个问题是,如果将其放在 pom.xml 中,则需要调用 assembly:single
目标,而如果从命令行手动执行,则需要调用 '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>
【讨论】:
【参考方案3】:如果你真的想在你的单个结果 JAR 中重新打包其他 JAR 内容,另一个选项是 Maven Assembly plugin。它解压缩然后通过<unpack>true</unpack>
将所有内容重新打包到一个目录中。然后你会有第二次通过,将它构建到一个巨大的 JAR 中。
Another option is the OneJar plugin。这一步完成了上述重新打包操作。
【讨论】:
【参考方案4】:在我看来,Ken Liu 说得对。 maven 依赖插件允许您扩展所有依赖项,然后您可以将其视为资源。这允许您将它们包含在 main 工件中。组装插件的使用创建了一个可能难以修改的辅助工件 - 在我的情况下,我想添加自定义清单条目。我的 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>
【讨论】:
【参考方案5】:您可以使用 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>
【讨论】:
【参考方案6】:我不会直接回答这个问题,因为其他人之前已经这样做了,但我真的想知道将所有依赖项嵌入到项目的 jar 本身中是否是个好主意。
我明白这一点(易于部署/使用),但这取决于您的项目的用例(并且可能有替代方案(见下文))。
如果你完全独立使用它,为什么不呢。
但是,如果您在其他上下文中使用您的项目(例如在 web 应用程序中,或者放在其他 jar 所在的文件夹中),您的类路径中可能有 jar 重复项(文件夹中的那些,jar 中的那个) )。也许不是出价交易,但我通常会避免这种情况。
一个不错的选择:
将您的应用程序部署为 .zip / .war:存档包含您项目的 jar 和所有依赖的 jar; 使用动态类加载器机制(请参阅 Spring,或者您可以自己轻松地执行此操作)拥有项目的单个入口点(启动单个类 - 请参阅另一个答案中的 Manifest 机制),这将添加(动态) 到当前类路径中所有其他需要的 jars。像这样,最后只有一个清单和一个“特殊的动态类加载器主程序”,您可以使用以下方式启动您的项目:
java -jar ProjectMainJar.jar com.***.projectName.MainDynamicClassLoaderClass
【讨论】:
【参考方案7】:应该是这样的:
<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>
解包必须在生成资源阶段,因为如果在打包阶段,将不会作为资源包含在内。 试试 clean package 你会看到的。
【讨论】:
得到这个问题:org.apache.maven.lifecycle.LifecycleExecutionException: Failed to execute goal org.apache.maven.plugins:maven-dependency-plugin:3.1.2:unpack-dependencies (unpack-依赖项)在项目服务上:未知的归档器类型【参考方案8】:要从命令行本身创建可执行 JAR,只需从项目路径运行以下命令:
mvn assembly:assembly
【讨论】:
我认为你仍然需要在pom.xml
中做一些事情,否则你会得到Error reading assemblies: No assembly descriptors found.
。反正我就是这样。【参考方案9】:
使用 maven-shade-plugin 将所有依赖项打包到一个 uber-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>
【讨论】:
【参考方案10】:您可以在打包阶段之前使用依赖插件在单独的目录中生成所有依赖项,然后将其包含在清单的类路径中:
<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。
【讨论】:
有没有办法在不编写自定义类加载器的情况下使用此方法?我收到“ClassNotFoundException”。当我比较程序集插件时,我想我可以使用 maven-dependency-plugin 解包依赖项。有什么建议吗?【参考方案11】:使用 maven-assembly-plugin-2.2.1 定位共享程序集文件时出现问题?
尝试使用descriptorId配置参数代替descriptor/descriptor或descriptorRefs/descriptorRef参数。
它们都不做您需要的事情:在类路径中查找文件。 当然,您需要在 maven-assembly-plugin 的类路径中添加共享程序集所在的包(见下文)。 如果您使用的是 Maven 2.x(不是 Maven 3.x),您可能需要在 pluginManagement 部分的最顶层父 pom.xml 中添加此依赖项。
更多详情请见this。
类: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>
【讨论】:
【参考方案12】:您可以将以下内容添加到您的 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>
之后,您必须通过控制台切换到 pom.xml 所在的目录。然后你必须执行 mvn assembly:single 然后你的可执行 JAR 文件与依赖将有望构建。您可以在使用 cd ./target 切换到输出(目标)目录并使用类似于 java -jar mavenproject1-1.0-SNAPSHOT-jar-with- 的命令启动 jar 时检查它依赖项.jar。
我使用 Apache Maven 3.0.3 对此进行了测试。
【讨论】:
【参考方案13】:您可以将maven-shade-plugin
和maven-jar-plugin
结合使用。
maven-shade-plugin
将您的类和所有依赖项打包在一个 jar 文件中。
配置maven-jar-plugin
以指定可执行jar 的主类(参见Set Up The Classpath,“使Jar 可执行”一章)。
maven-jar-plugin
的示例 POM 配置:
<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>
最后通过调用创建可执行jar:
mvn clean package shade:shade
【讨论】:
Shade 插件现在可以在清单中指定 Main-Class 条目:maven.apache.org/plugins/maven-shade-plugin/examples/…【参考方案14】:长期使用maven 程序集插件,但我找不到解决"already added, skipping"
问题的方法。现在,我正在使用另一个插件 - onejar-maven-plugin。下面的示例(mvn package
build 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>
您需要为该插件添加存储库:
<pluginRepositories>
<pluginRepository>
<id>onejar-maven-plugin.googlecode.com</id>
<url>http://onejar-maven-plugin.googlecode.com/svn/mavenrepo</url>
</pluginRepository>
</pluginRepositories>
【讨论】:
【参考方案15】:maven-assembly-plugin 非常适合我。
我花了几个小时使用 maven-dependency-plugin 并且无法使其工作。主要原因是我必须在配置部分明确定义应该包含的工件项,如documentation 中所述。
当您想使用它时,有一个示例:mvn dependency:copy
,其中没有包含任何 artifactItems 但它不起作用。
【讨论】:
【参考方案16】:对我有用的是:
<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>
我遇到了特殊情况,因为我的依赖是系统一:
<dependency>
..
<scope>system</scope>
<systemPath>$project.basedir/lib/myjar.jar</systemPath>
</dependency>
我已经更改了@user189057 提供的代码并进行了更改: 1) maven-dependency-plugin 在“prepare-package”阶段执行 2)我将解压的类直接提取到“目标/类”
【讨论】:
【参考方案17】:见executable-jar-with-maven-example (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 可执行并识别类路径
<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)。<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.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>
你有target/$project.build.finalName-shaded.jar
。
onejar-maven-plugin
优点 缺点 自 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.bulid.finalName-spring-boot.jar
。
【讨论】:
【参考方案18】:我在这里尝试了投票最多的答案,并且能够使 jar 可运行。但是程序没有正确运行。我不知道是什么原因。当我尝试从 Eclipse
运行时,我得到了不同的结果,但是当我从命令行运行 jar 时,我得到了不同的结果(它因程序特定的运行时错误而崩溃)。
我有与 OP 类似的要求,只是我的项目有太多 (Maven) 依赖项。幸运的是,唯一对我有用的解决方案是使用Eclipse
。非常简单,非常直接。这不是针对 OP 的解决方案,而是针对具有类似需求但具有许多 Maven 依赖项的人的解决方案,
1) 只需右键单击您的项目文件夹(在 Eclipse 中)并选择Export
2) 然后选择Java
-> Runnable Jar
3) 系统会要求您选择 jar 文件的位置
4) 最后选择要运行的Main方法所在的类,选择Package dependencies with the Jar file
,点击Finish
【讨论】:
【参考方案19】:好的,这就是我的解决方案。我知道它没有使用 pom.xml 文件。但是我的程序在 Netbeans 上编译和运行时遇到了问题,但是当我尝试 Java -jar MyJarFile.jar 时它失败了。现在,我并不完全了解 Maven,我认为这就是为什么让 Netbeans 8.0.2 无法将我的 jar 文件包含在库中以将它们放入 jar 文件中的原因。我正在考虑如何在 Eclipse 中使用没有 Maven 的 jar 文件。
它是 Maven 可以编译所有依赖项和插件。不是 Netbeans。 (如果您可以获得 Netbeans 并能够使用 java .jar 来执行此操作,请告诉我如何 (^.^)v)
[已解决 - 适用于 Linux] 通过打开终端。
然后
cd /MyRootDirectoryForMyProject
下一个
mvn org.apache.maven.plugins:maven-compiler-plugin:compile
下一个
mvn install
这将在目标目录中创建 jar 文件。
MyJarFile-1.0-jar-with-dependencies.jar
现在
cd target
(您可能需要运行:chmod +x MyJarFile-1.0-jar-with-dependencies.jar
)
最后
java -jar MyJarFile-1.0-jar-with-dependencies.jar
请看
https://cwiki.apache.org/confluence/display/MAVEN/LifecyclePhaseNotFoundException
我会将此解决方案发布在其他几个有类似问题的页面上。希望我能将某人从一周的挫折中拯救出来。
【讨论】:
尝试打开您使用 Netbeans 创建的 Maven 项目。 Netbeans 的基本规则始终是创建一个 Maven 项目,而不是一个“Java 应用程序”。添加一个 maven-shade-plugin 就像答案之一一样。像魅力一样工作。【参考方案20】:这是我发现的最好方法:
<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>
使用此配置,所有依赖项都将位于/dependency-jars
。我的应用程序没有 Main
类,只有上下文类,但我的一个依赖项确实有一个 Main
类 (com.myDomain.etc.MainClassName
),它启动 JMX 服务器,并接收 start
或 stop
参数。所以有了这个,我可以像这样启动我的应用程序:
java -jar ./lib/TestApp-1.0-SNAPSHOT.jar start
我等待它对大家有用。
【讨论】:
【参考方案21】:这篇博文展示了另一种结合 maven-jar 和 maven-assembly 插件的方法。使用博客文章中的程序集配置 xml,还可以控制是否扩展依赖项或仅将其收集在文件夹中并由清单中的类路径条目引用:
理想的解决方案是将 jar 包含在 lib 文件夹中,并且主 jar 的 manifest.mf 文件包含类路径中的所有 jar。
这里就是这样描述的:https://caffebig.wordpress.com/2013/04/05/executable-jar-file-with-dependent-jars-using-maven/
【讨论】:
【参考方案22】:我查看了这些响应中的每一个,希望制作一个包含所有依赖项的胖可执行 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>
请注意,您的依赖项需要具有编译或运行时范围才能正常工作。
This example came from mkyong.com
【讨论】:
【参考方案23】:这也可以是一个选项,您将能够构建您的 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>
【讨论】:
【参考方案24】:我比较了这篇文章中提到的树插件。我生成了 2 个 jar 和一个包含所有 jar 的目录。我比较了结果,肯定 maven-shade-plugin 是最好的。我的挑战是我有多个需要合并的 spring 资源,以及 jax-rs 和 JDBC 服务。与 maven-assembly-plugin 相比,它们都被 shade 插件正确合并。在这种情况下,除非您将它们复制到自己的资源文件夹并手动合并一次,否则 spring 将失败。两个插件都输出正确的依赖树。我有多个范围,如测试、提供、编译等,两个插件都跳过了测试和提供的范围。他们都产生了相同的清单,但我能够使用他们的转换器将许可证与阴影插件合并。 使用 maven-dependency-plugin 当然你没有这些问题,因为 jars 没有被提取。但就像其他人指出的那样,您需要携带一个额外的文件才能正常工作。 这是 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>
【讨论】:
【参考方案25】:对于任何寻找从 uber-jar 中排除特定依赖项的选项的人,这是一个对我有用的解决方案:
<project...>
<dependencies>
<dependency>
<groupId>org.apache.spark</groupId>
<artifactId>spark-core_2.11</artifactId>
<version>1.6.1</version>
<scope>provided</scope> <=============
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<configuration>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
<archive>
<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-assembly-plugin 的配置,而是依赖项的属性。
【讨论】:
【参考方案26】:为了解决这个问题,我们将使用 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>
完成此操作后不要忘记使用此命令运行 MAVEN 工具 mvn clean compile assembly:single
http://jkoder.com/maven-creating-a-jar-together-with-its-dependency-jars-into-a-single-executable-jar-file/
【讨论】:
【参考方案27】:已经有数百万个答案,如果您不需要将 entryPoint 添加到您的应用程序,我想添加您不需要<mainClass>
。 例如 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>
构建
mvn clean compile assembly:single
验证
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/
【讨论】:
【参考方案28】:添加到 pom.xml:
<dependency>
<groupId>com.jolira</groupId>
<artifactId>onejar-maven-plugin</artifactId>
<version>1.4.4</version>
</dependency>
和
<plugin>
<groupId>com.jolira</groupId>
<artifactId>onejar-maven-plugin</artifactId>
<version>1.4.4</version>
<executions>
<execution>
<goals>
<goal>one-jar</goal>
</goals>
</execution>
</executions>
</plugin>
就是这样。下一个 mvn 包还会额外创建一个 fat jar,包括所有依赖 jar。
【讨论】:
【参考方案29】:您可以使用 maven-shade 插件来构建一个 uber 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>
【讨论】:
【参考方案30】:<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>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?的主要内容,如果未能解决你的问题,请参考以下文章
如何使用 Gradle 创建具有实现依赖项的可执行胖 jar
Maven中的可选依赖(Optional Dependencies)和依赖排除(Dependency Exclusions)