是否可以指定一个classpath
包含另一个 JAR 文件中的 JAR 文件的 Java?
14 回答
您不想使用那些“爆炸 JAR 内容”解决方案。它们肯定会让东西更难看(因为所有东西都在同一水平上爆炸)。此外,可能存在命名冲突(如果人们使用正确的包,则不应发生,但您不能总是控制这一点)。
您想要的功能是25 大 Sun RFE之一:RFE 4648386,Sun 以其无限的智慧将其指定为低优先级。我们只能希望太阳醒来......
同时,我遇到的最佳解决方案(我希望 Sun 将其复制到 JDK 中)是使用自定义类加载器JarClassLoader。
经过一些研究,我发现了不需要 maven 或任何 3rd 方扩展/程序的方法。
您可以在清单文件中使用“类路径”。
例如:
创建清单文件 MANIFEST.MF
Manifest-Version: 1.0
Created-By: Bundle
Class-Path: ./custom_lib.jar
Main-Class: YourMainClass
编译所有类并运行jar cfm Testing.jar MANIFEST.MF *.class custom_lib.jar
c
代表 create archive
f
表示要指定 file
v
是用于详细输入
m
表示我们将传递自定义清单文件
确保在 jar 包中包含 lib。您应该能够以正常方式运行 jar。
基于:http ://www.ibm.com/developerworks/library/j-5things6/
你需要的关于类路径的所有其他信息都在这里找到吗
使用zipgroupfileset标签(使用与文件集标签相同的属性);它将解压缩目录中的所有文件并添加到您的新存档文件中。更多信息:http ://ant.apache.org/manual/Tasks/zip.html
这是解决 jar-in-a-jar 问题的一种非常有用的方法——我知道是因为我在试图弄清楚该怎么做时搜索了这个确切的 StackOverflow 问题。如果你想将一个 jar 或一个 jar 文件夹打包到你用 Ant 构建的 jar 中,那么忘记所有这些类路径或第三方插件的东西,你所要做的就是(在 Ant 中):
<jar destfile="your.jar" basedir="java/dir">
...
<zipgroupfileset dir="dir/of/jars" />
</jar>
如果您正在使用 ant 构建(我正在使用来自 eclipse 的 ant),您可以通过告诉 ant 添加额外的 jar 文件来添加它们......如果您有一个由多人维护的项目,这不一定是最好的方法,但它可以工作对于一个人的项目,很容易。
例如,我构建 .jar 文件的目标是:
<jar destfile="${plugin.jar}" basedir="${plugin.build.dir}">
<manifest>
<attribute name="Author" value="ntg"/>
................................
<attribute name="Plugin-Version" value="${version.entry.commit.revision}"/>
</manifest>
</jar>
我只是添加了一行来实现它:
<jar ....">
<zipgroupfileset dir="${external-lib-dir}" includes="*.jar"/>
<manifest>
................................
</manifest>
</jar>
在哪里
<property name="external-lib-dir"
value="C:\...\eclipseWorkspace\Filter\external\...\lib" />
是带有外部罐子的目录。就是这样……
并非没有编写自己的类加载器。您可以将 jars 添加到 jar 的类路径中,但它们必须位于同一位置,而不是包含在主 jar 中。
您需要构建一个自定义类加载器来执行此操作,或者构建一个支持此功能的第三方库。最好的办法是从运行时提取 jar 并将它们添加到类路径中(或者已经将它们添加到类路径中)。
我将 maven 用于我的 java 构建,它有一个名为maven assembly plugin的插件。
它可以满足您的要求,但就像其他一些建议所描述的那样-本质上是爆炸所有依赖的罐子并将它们重新组合成一个罐子
如果您有 eclpise IDE,您只需导出您的 JAR 并选择“将所需的库打包到生成的 JAR 中”。eclipse 会自动将所需的依赖 JAR 添加到生成的 JAR 中,并生成一些自动加载这些 JAR 的 eclipse 自定义类加载器。
我正要建议提取同一级别的所有文件,然后从结果中制作一个 jar,因为包系统应该将它们整齐地分开。那将是手动方式,我想史蒂夫指出的工具会很好地做到这一点。
Winstone 相当不错http://blog.jayway.com/2008/11/28/executable-war-with-winstone-maven-plugin/。但不适用于复杂的网站。这是一种耻辱,因为只需要包含插件。
好吧,如果您使用的是 Eclipse,那么有一个非常简单的方法。
将您的项目导出为“可运行”Jar 文件(在 Eclipse 中右键单击项目文件夹,选择“导出...”)。配置导出设置时,请务必选择“将所需库提取到生成的 Jar 中”。请记住,选择“提取...”而不是“打包所需的库...”。
另外:您必须在导出设置中选择运行配置。因此,您总是可以在某个类中创建一个空的 main() 并将其用于您的运行配置。
无论如何,它不能保证100% 的时间 - 因为您会注意到一条弹出消息,告诉您确保检查您包含的 Jar 文件的许可证以及不复制签名文件的一些内容。但是,我已经这样做了多年,从未遇到过问题。
提取到 Uber-dir 对我有用,因为我们都应该使用 root:\java 并且在带有版本控制的包中拥有 outlet 代码。即ca.tecreations-1.0.0。签名没问题,因为 jar 从其下载位置完好无损。3rd 方签名完整,解压到 c:\java。这是我的项目目录。从启动器运行 java -cp c:\java Launcher
如果您使用的是 Spring Boot,您可能需要查看以下文档:The Executable Jar Format
Java 不提供任何标准方法来加载嵌套的 jar 文件(即,本身包含在 jar 中的 jar 文件)。如果您需要分发可以从命令行运行而无需解包的独立应用程序,这可能会出现问题。
为了解决这个问题,许多开发人员使用“阴影”罐子。带阴影的 jar 将所有 jar 中的所有类打包到一个“uber jar”中。带阴影的 jar 的问题是很难看出哪些库实际上在您的应用程序中。如果在多个 jar 中使用相同的文件名(但内容不同),也可能会出现问题。Spring Boot 采用了不同的方法,让您实际上可以直接嵌套 jar。
Spring 文档还列出了一些替代的单 Jar 解决方案: