首页 > 解决方案 > 图书馆找不到自己的“子图书馆”

问题描述

我正在尝试用 Java 创建一个地址列表,它将其内容保存在 Sqlite 数据库中。

为此(以及其他未来用途),我尝试为各种数据库连接创建自己的库(“PentagonsDatabaseConnector-1.0.jar”)。它目前支持 Sqlite 和 MySql。

它为他们引用其他库来提供 JDBC 驱动程序(“mysql-connector-java-8.0.16.jar”和“sqlite-jdbc-3.30.1.jar”)。

问题:如果我从它自己的项目文件夹中访问它,我的库工作得很好,但是一旦我编译它并将它添加到“Adressliste”项目中,它就无法再找到 JDBC 驱动程序了(我可以毫无问题地访问我自己编写的库的其余部分)。此外,如屏幕截图所示,“PentagonsDatabaseConnector-1.0.jar”将 JDBC 库与自身放在“lib”文件夹中。

屏幕截图链接

你们有什么想法吗?

谢谢您的帮助!

Ps:对不起英语不好,我是德国人:)

标签: javaeclipseexport

解决方案


Java 无法读取 jars-in-jars。

依赖项有几种形式。在这种情况下,PentagonsDC 是一个正常的依赖;它必须在运行时存在,并且在编译时也存在。

JDBC 库有点特别。它们是仅运行时的部门。您不需要它们在编译时出现。你想要这个,因为 JDBC 库作为一个概念是可插拔的。

好的,那我该怎么办?

使用构建系统来管理您的依赖项是 90% 以上的 Java 程序员的答案,我建议您在这里做。特别是对于刚起步的人,我建议Maven。在这里,您只需将依赖项的名称放入一个文本文件中,maven 就会处理它,至少在编译时是这样。

对于运行时方面,您有几个选择。这取决于您的 java 应用程序如何运行。

一些例子:

基于清单的类路径

您“独立”运行您的 java 应用程序,例如,您编写了psv main(String[])启动应用程序的方法,并将其分发到需要运行的任何地方。在这种情况下,通常的策略是拥有一个安装程序(您需要在客户端上安装一个 JVM 来运行您的应用程序,并且 Oracle 和任何操作系统供应商都不再支持在最终用户的系统上维护一个正常运行的 JVM;现在这是您的工作——这不幸的是,这不是微不足道的),并且鉴于您拥有它,您应该部署您的 jar,使其包含在清单中(jar 是 zip,清单最终位于 META-INF/MANIFEST.MF):

Main-Class: com.of.yourproj.Main
Class-Path: lib/sqlite-jdbc.jar lib/mysql-jdbc.jar lib/guava.jar

然后有一个像这样的目录结构:

C:\Program Files\yourapp\yourapp.jar
C:\Program Files\yourapp\lib\sqlite-jdbc.jar
C:\Program Files\yourapp\lib\mysql-jdbc.jar

或任何其他操作系统上的等价物。清单中的类路径条目是空格分隔的,并相对于 'yourapp.jar' 所在的目录进行解析。这样,您可以从任何地方运行 yourapp.jar,它以及 Class-Path 中列出的所有条目现在都可用给它。

构建工具可以为您实现这一点。

阴影/ Uberjars

阴影是将所有东西打包成一个巨大的罐子的概念。不是 jars-in-jars,而是将依赖项 jar 的内容解压缩到主应用程序 jar 中。这在构建中可能会很慢(如果您有几百 MB 的 deps,则需要将它们打包,并且所有类文件都需要分析以进行阴影重写,这需要处理很多位,因此总是需要一些时间)。阴影背后的一般想法是部署“就像传输一个 jar 文件一样简单”,但这实际上并不实用,因为您不能再假设最终用户安装了 JVM,即使他们安装了,您也不能依赖关于它是否正确更新。我在这里提到它是因为您可能会从其他人那里听到这个,但我不会推荐它。

如果你真的想这样做,唯一的选择是构建系统:他们有一个插件来做;没有随 java 本身一起提供的命令行工具可以做到这一点。还有一些关于所谓的“签名罐子”的警告,它不能被解压到一个单独的 uberjar 中。

应用容器

并非所有 java 应用程序都是独立的,您提供主要的。例如,如果您正在编写 Web 服务,那么您根本就没有 main;框架确实如此。Web 服务有大量的入口点,而不是单个入口点('main' - 你的代码最初开始执行的地方):每个你想要响应的 URL 都有一个入口点。框架负责调用它们,并且通常这些框架有自己的文档和规范来说明如何加载依赖项。通常是将一个 jar 放在一个地方,并将它的依赖项放在一个名为“lib”的子目录中,或者你构建一个所谓的 war 文件,但是,实际上,有这么多的 Web 框架和这么多关于它们如何做到这一点的选项. 好消息是,通常它很简单,并且该框架的教程将涵盖它。

此建议适用于任何“应用容器”系统;这些通常是 Web 框架,但也有一些与 Web 无关的框架负责启动您的应用程序。

不要做这些

不要强迫您的用户手动提供-classpath选项或弄乱CLASSPATH环境变量。

不要尝试编写加载 jars-in-jars 的自定义类加载器。

注意:Sqlite2 对于 java 来说相当复杂;它并没有给你带来'lite'应该给你带来的许多好处,因为它是一个原生依赖项。在 java 领域中,简单的、随处可用的解决方案是“h2”,它是用所有 java 编写的,因此可以使用零个本地组件将整个 h2 引擎作为 java 应用程序的一部分提供。


推荐阅读