用Maven在jar中包含依赖项
有没有办法强制maven(2.0.9)将所有的依赖包括在一个jar文件中?
我有一个项目构build到一个单一的jar文件。 我想从依赖的类也复制到jar中。
更新:我知道我不能在一个jar文件中包含一个jar文件。 我正在寻找一种方法来解压指定为依赖的jar包,并将类文件打包到jar中。
你可以使用maven-assembly插件和“jar-with-dependencies”描述符来做到这一点。 下面是我们的一个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可执行,只需要将要运行的主类添加到插件configuration:
<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>
如果你想创build这个程序集作为正常的构build过程的一部分,你应该将单个 目录或目录单一目标( 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
元素以满足您的需求(例如使用清单内容)。
有阴影maven插件 。 它可以用来打包和重命名依赖关系(省略类path上的依赖关系问题)。
如果你(像我)不喜欢上述jar-with-dependencies方法,我更喜欢的maven解决scheme是简单地构build一个WAR项目,即使它只是一个独立的Java应用程序正在构build:
-
做一个正常的maven jar-project,这将会build立你的jar文件(没有依赖关系)。
-
另外,设置一个maven war-project(只有一个空的src / main / webapp / WEB-INF / web.xml文件,这将避免maven-build中的警告/错误),只有你的jar-project作为一个依赖关系,并让你的jar-project在你的war-project下是一个
<module>
。 (这个战争项目只是一个简单的技巧,把你所有的jar文件依赖包装到一个zip文件中。) -
build立战争项目来制作战争档案。
-
在部署步骤中,只需将.war文件重命名为* .zip并将其解压。
你现在应该有一个lib目录(你可以移动到你想要的地方),用你的jar和运行你的应用程序所需的所有依赖:
java -cp 'path/lib/*' MainClass
(classpath中的通配符在Java-6或更高版本中工作)
我认为这在maven中设置更简单(不需要乱用程序集插件),也给了你更清晰的应用程序结构视图(你可以在普通视图中看到所有相关jar的版本号,避免堵塞一切到一个单一的jar文件)。
您可以使用<classifier>
标签使用新创build的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>
http://fiji.sc/Uber-JAR提供了一个很好的解释:;
有三种常用的构build超级JAR的方法:
- 无阴影。 解压所有的JAR文件,然后将它们重新打包成一个JAR文件。
- Pro:适用于Java的默认类加载器。
- Con:存在于具有相同path的多个JAR文件(例如,META-INF / services / javax.script.ScriptEngineFactory)中的文件将相互覆盖,导致错误的行为。
- 工具:Maven Assembly Plugin,Classworlds Uberjar
- 阴影。 与无阴影相同,但重命名(即“阴影”)所有依赖关系的所有包。
- Pro:适用于Java的默认类加载器。 避免一些(不是全部)依赖版本的冲突。
- Con:存在于具有相同path的多个JAR文件(例如,META-INF / services / javax.script.ScriptEngineFactory)中的文件将相互覆盖,导致错误的行为。
- 工具:Maven Shade插件
- JAR的JAR。 最终的JAR文件包含embedded其中的其他JAR文件。
- 专业版:避免依赖版本冲突。 所有资源文件都被保留。
- Con:需要捆绑一个特殊的“引导”类加载器,使Java能够从被包装的JAR文件中加载类。 debugging类加载器问题变得更加复杂。
- 工具:Eclipse JAR文件导出器,One-JAR。
如果你想做一个可执行的jar文件,他们也需要设置主类。 所以完整的configuration应该是。
<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>
我在Eclipse Luna和m2eclipse上定义的解决scheme:自定义类加载器(下载并添加到您的项目,仅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清洁依赖:复制依赖包
是用一个瘦类加载器在lib文件夹中创build一个依赖关系的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库放到主Jar中,但是你需要使用你自己的类加载器。
检查这个项目:单JAR 链接文本
这个post可能有点老了,但是我最近也有同样的问题。 John Stauffer提出的第一个解决scheme是一个很好的解决scheme,但是今年spring我工作时遇到了一些问题。 我使用的spring的dependency-jar有一些属性文件和xml-schemas声明,它们共享相同的path和名称。 虽然这些jar来自同一个版本,但是jar-with-dependencies maven-goal覆盖了最后find的文件。
最后,应用程序无法启动,因为弹簧jar无法find正确的属性文件。 在这种情况下,Rop提出的解决scheme已经解决了我的问题。
从那时起,春季启动项目就已经存在。 它提供了一个非常好的方法来pipe理这个问题,它提供了一个超载包目标并提供自己的类加载器的maven目标。 参见“ 弹簧靴参考指南”
看看这个答案:
我正在创build一个作为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>
谢谢我在POM.xml文件中添加了下面的代码片段并解决了Mp问题,并创build了包含所有相关jar的fat 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>