[英]Including dependencies in a jar with Maven
有没有办法强制 maven(2.0.9) 将所有依赖项包含在一个 jar 文件中?
我有一个构建到单个 jar 文件中的项目。 我还希望将依赖项中的类复制到 jar 中。
更新:我知道我不能只在 jar 文件中包含一个 jar 文件。 我正在寻找一种方法来将指定为依赖项的 jars 和 package 文件解压缩到我的 jar 中。
您可以使用带有“jar-with-dependencies”描述符的 maven-assembly 插件来做到这一点。 这是我们的 pom.xml 之一的相关块,它执行此操作:
<build>
<plugins>
<!-- any other plugins -->
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
</execution>
</executions>
<configuration>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
</configuration>
</plugin>
</plugins>
</build>
使用 Maven 2,正确的方法是使用Maven2 Assembly Plugin ,它具有用于此目的的预定义描述符文件,您可以在命令行上使用它:
mvn assembly:assembly -DdescriptorId=jar-with-dependencies
如果要使这个 jar 可执行,只需将要运行的主类添加到插件配置中:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-assembly-plugin</artifactId>
<configuration>
<archive>
<manifest>
<mainClass>my.package.to.my.MainClass</mainClass>
</manifest>
</archive>
</configuration>
</plugin>
如果您想在正常构建过程中创建该程序集,您应该将单一或目录单一目标( assembly
目标只能从命令行运行)绑定到生命周期阶段( package
有意义),例如这个:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-assembly-plugin</artifactId>
<executions>
<execution>
<id>create-my-bundle</id>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
<configuration>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
...
</configuration>
</execution>
</executions>
</plugin>
调整configuration
元素以满足您的需求(例如,使用清单内容作为口语)。
如果你想做一个可执行的jar文件,他们也需要设置主类。 所以完整的配置应该是。
<plugins>
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
</execution>
</executions>
<configuration>
<!-- ... -->
<archive>
<manifest>
<mainClass>fully.qualified.MainClass</mainClass>
</manifest>
</archive>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
</configuration>
</plugin>
</plugins>
有 阴影 maven 插件。 它可用于打包和重命名依赖项(以省略类路径上的依赖项问题)。
您可以使用<classifier>
标签使用新创建的 jar。
<dependencies>
<dependency>
<groupId>your.group.id</groupId>
<artifactId>your.artifact.id</artifactId>
<version>1.0</version>
<type>jar</type>
<classifier>jar-with-dependencies</classifier>
</dependency>
</dependencies>
如果你(像我一样)不是特别喜欢上面描述的jar-with-dependencies方法,我更喜欢的 maven-solution 是简单地构建一个 WAR 项目,即使它只是你正在构建的一个独立的 java 应用程序:
制作一个普通的 Maven jar 项目,它将构建您的 jar 文件(没有依赖项)。
此外,设置一个 maven 战争项目(只有一个空的src/main/webapp/WEB-INF/web.xml文件,这将避免 maven-build 中的警告/错误),只有你的 jar-project 作为一个依赖项,并使您的 jar-project 在您的 war-project 下成为<module>
。 (这个战争项目只是将所有 jar 文件依赖项包装到一个 zip 文件中的简单技巧。)
构建战争项目以生成战争文件。
在部署步骤中,只需将您的 .war 文件重命名为 *.zip 并将其解压缩。
您现在应该有一个包含 jar 和运行应用程序所需的所有依赖项的 lib 目录(您可以将其移动到您想要的位置):
java -cp 'path/lib/*' MainClass
(类路径中的通配符适用于 Java-6 或更高版本)
我认为这在 maven 中设置起来更简单(不需要弄乱程序集插件),并且还为您提供了更清晰的应用程序结构视图(您将在普通视图中看到所有依赖 jar 的版本号,并且避免将所有内容堵塞到单个 jar 文件中)。
http://fiji.sc/Uber-JAR提供了对替代方案的极好解释:
构建 uber-JAR 的常用方法有以下三种:
- 无阴影。 解压所有 JAR 文件,然后将它们重新打包成单个 JAR。
- 优点:适用于 Java 的默认类加载器。
- 缺点:存在于具有相同路径的多个 JAR 文件中的文件(例如 META-INF/services/javax.script.ScriptEngineFactory)将相互覆盖,从而导致错误行为。
- 工具:Maven Assembly Plugin、Classworlds Uberjar
- 阴影。 与 unshaded 相同,但重命名(即“shade”)所有依赖项的所有包。
- 优点:适用于 Java 的默认类加载器。 避免一些(不是全部)依赖版本冲突。
- 缺点:存在于具有相同路径的多个 JAR 文件中的文件(例如 META-INF/services/javax.script.ScriptEngineFactory)将相互覆盖,从而导致错误行为。
- 工具:Maven Shade Plugin
- JAR 的 JAR。 最终的 JAR 文件包含嵌入其中的其他 JAR 文件。
- 优点:避免依赖版本冲突。 保留所有资源文件。
- 缺点:需要捆绑一个特殊的“引导”类加载器,使 Java 能够从包装的 JAR 文件中加载类。 调试类加载器问题变得更加复杂。
- 工具:Eclipse JAR 文件导出器,One-JAR。
<!-- Method 1 -->
<!-- Copy dependency libraries jar files to a separated LIB folder -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<configuration>
<outputDirectory>${project.build.directory}/lib</outputDirectory>
<excludeTransitive>false</excludeTransitive>
<stripVersion>false</stripVersion>
</configuration>
<executions>
<execution>
<id>copy-dependencies</id>
<phase>package</phase>
<goals>
<goal>copy-dependencies</goal>
</goals>
</execution>
</executions>
</plugin>
<!-- Add LIB folder to classPath -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>2.4</version>
<configuration>
<archive>
<manifest>
<addClasspath>true</addClasspath>
<classpathPrefix>lib/</classpathPrefix>
</manifest>
</archive>
</configuration>
</plugin>
<!-- Method 2 -->
<!-- Package all libraries classes into one runnable jar -->
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
</execution>
</executions>
<configuration>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
</configuration>
</plugin>
我在 Eclipse Luna 和 m2eclipse 上的最终解决方案:自定义类加载器(下载并添加到您的项目,仅 5 个类): http : //git.eclipse.org/c/jdt/eclipse.jdt.ui.git/plain/org。 eclipse.jdt.ui/jar%20in%20jar%20loader/org/eclipse/jdt/internal/jarinjarloader/ ; 这个类加载器是单 jar 类加载器中最好的,而且速度非常快;
<project.mainClass>org.eclipse.jdt.internal.jarinjarloader.JarRsrcLoader</project.mainClass> <project.realMainClass>my.Class</project.realMainClass>
在 JIJConstants 中将“Rsrc-Class-Path”编辑为“Class-Path”
mvn clean dependency:copy-dependencies包
使用瘦类加载器在 lib 文件夹中创建了一个具有依赖项的 jar
<build>
<resources>
<resource>
<directory>src/main/java</directory>
<includes>
<include>**/*.java</include>
<include>**/*.properties</include>
</includes>
</resource>
<resource>
<directory>src/main/resources</directory>
<filtering>true</filtering>
<includes>
<include>**/*</include>
</includes>
<targetPath>META-INF/</targetPath>
</resource>
<resource>
<directory>${project.build.directory}/dependency/</directory>
<includes>
<include>*.jar</include>
</includes>
<targetPath>lib/</targetPath>
</resource>
</resources>
<pluginManagement>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<configuration>
<archive>
<manifest>
<addClasspath>true</addClasspath>
<mainClass>${project.mainClass}</mainClass>
<classpathPrefix>lib/</classpathPrefix>
</manifest>
<manifestEntries>
<Rsrc-Main-Class>${project.realMainClass} </Rsrc-Main-Class>
<Class-Path>./</Class-Path>
</manifestEntries>
</archive>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<executions>
<execution>
<id>copy-dependencies</id>
<phase>package</phase>
<goals>
<goal>copy-dependencies</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</pluginManagement>
</build>
抛开 Maven,您可以将 JAR 库放在 Main Jar 中,但您需要使用自己的类加载器。
检查此项目:One-JAR链接文本
谢谢我在 POM.xml 文件中添加了以下代码段,解决了 Mp 问题并创建了包含所有依赖 jar 的胖 jar 文件。
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
</execution>
</executions>
<configuration>
<descriptorRefs>
<descriptorRef>dependencies</descriptorRef>
</descriptorRefs>
</configuration>
</plugin>
</plugins>
这个帖子可能有点旧,但我最近也遇到了同样的问题。 John Stauffer 提出的第一个解决方案是一个很好的解决方案,但我在今年春天工作时遇到了一些问题。 我使用的 spring 的依赖 jars 有一些属性文件和 xml-schemas 声明,它们共享相同的路径和名称。 尽管这些 jar 来自相同的版本,但jar-with-dependencies maven-goal 正在用找到的最后一个文件覆盖这些文件。
最后,应用程序无法启动,因为 spring jars 找不到正确的属性文件。 在这种情况下,Rop 提出的解决方案解决了我的问题。
也是从那时起,spring-boot 项目就存在了。 通过提供一个 maven 目标来重载包目标并提供自己的类加载器,它有一种非常酷的方法来管理这个问题。 参见spring-boots 参考指南
我正在创建一个作为 Java JAR 文件运行的安装程序,它需要将 WAR 和 JAR 文件解压缩到安装目录中的适当位置。 依赖插件可以在具有复制目标的包阶段使用,它将下载 Maven 存储库中的任何文件(包括 WAR 文件)并将它们写入您需要的任何地方。 我将输出目录更改为 ${project.build.directory}/classes 然后最终结果是正常的 JAR 任务包含我的文件就好了。 然后我可以提取它们并将它们写入安装目录。
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<executions>
<execution>
<id>getWar</id>
<phase>package</phase>
<goals>
<goal>copy</goal>
</goals>
<configuration>
<artifactItems>
<artifactItem>
<groupId>the.group.I.use</groupId>
<artifactId>MyServerServer</artifactId>
<version>${env.JAVA_SERVER_REL_VER}</version>
<type>war</type>
<destFileName>myWar.war</destFileName>
</artifactItem>
</artifactItems>
<outputDirectory>${project.build.directory}/classes</outputDirectory>
</configuration>
</execution>
</executions>
为了使它更简单,您可以使用以下插件。
<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.nirav.certificate.CertificateUtility
</mainClass>
</configuration>
</execution>
</executions>
</plugin>
我试图做类似的事情,但我不想包括所有的罐子。 我想从给定的依赖项中包含一些特定的目录。 另外分类器标签已经被占用,所以我不能这样做:
<dependencies>
<dependency>
<groupId>your.group.id</groupId>
<artifactId>your.artifact.id</artifactId>
<version>1.0</version>
<type>jar</type>
<classifier>jar-with-dependencies</classifier>
</dependency>
</dependencies>
${project.build.directory}/classes
,否则会被省略<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<executions>
<execution>
<id>unpack</id>
<phase>prepare-package</phase>
<goals>
<goal>unpack</goal>
</goals>
<configuration>
<artifactItems>
<artifactItem>
<groupId>my.group</groupId>
<artifactId>my.artifact</artifactId>
<classifier>occupied</classifier>
<version>1.0</version>
<type>jar</type>
</artifactItem>
</artifactItems>
<outputDirectory>${project.build.directory}/classes</outputDirectory>
<includes>aaa/**, bbb/**, ccc/**</includes>
</configuration>
</execution>
</executions>
</plugin>
我发现这是最明确的答案; 这里的其他答案缺少对我来说不明显的东西,例如 mvn clean package 命令,以及单独添加插件作为依赖项。 对于习惯使用 maven 的用户来说,所有这些可能都是显而易见的。
https://howtodoinjava.com/maven/executable-jar-with-dependencies/
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.