繁体   English   中英

运行生成的 jar 文件时,如何使 Apache Derby 数据库正常工作?

[英]How can I make my Apache Derby database work when I run my generated jar file?

我创建了一个 JavaFX 应用程序,并生成了一个将启动的 Jar 文件(使用 Gradle 生成)。

当应用程序启动时,它不会连接到嵌入式数据库。 我觉得好像我错过了一些非常简单的东西,但经过大量研究,我一直无法弄清楚。 从命令提示符运行 jar 文件时,出现以下错误:java.lang.ClassNotFoundException: org.apache.derby.jdbc.EmbeddedDriver

从我所做的阅读中,我知道我可以将它添加到我的类路径中,但是在多次尝试后我没有成功,我已经让这个应用程序在另一台计算机上运行。 可能的,对吧?

如果可能的话,我很想更改我的 build.gradle 文件中的某些内容,或者将 .jar 包含在一个文件夹中或类似的东西中,这将使运行程序的人变得简单。 程序大小不是几个千兆字节的问题。

你有两个问题

  • 驱动程序类不在您的应用程序 jar 中
  • 如果您将该数据库嵌入到应用程序 jar 中,您将无法写入它

你可以做一个“胖罐子”,但这不会解决第二个问题。 您确实需要制作一个安装程序来执行此操作,以便将 db 保留在文件系统中,以便可以将其写入。

问题

Gradle 所做的部分工作是依赖管理 这意味着它知道您需要哪些依赖项以及如何找到它们(基于构建脚本中的配置)。 当您通过 Gradle 执行/构建应用程序时,该工具将自动搜索存储库、下载+缓存依赖项,并将这些依赖项放在类路径/模块路径上。 一旦您部署了 JAR 文件,Gradle 就不再涉及,因此您的部署负责包括所需的依赖项。

换句话说,您需要将应用程序的依赖项与应用程序 JAR 文件一起发送。


解决方案

您基本上只需要确保将应用程序的依赖项包含在您的应用程序中。 这里至少有三种方法可以做到这一点。

复制依赖

作为构建过程的一部分,将依赖项复制到构建文件夹中。 这是使用Kotlin DSL执行此类任务的示例:

tasks {
    val jar by existing(Jar::class)

    val copyDependencies by registering(Copy::class) {
        from(configurations.runtimeClasspath)
        into(jar.get().destinationDirectory)
    }

    jar.configure {
        finalizedBy(copyDependencies)
    }
}

现在,如果您执行./gradlew jar Gradle 将创建 JAR 文件,然后将依赖项复制到与 JAR 文件相同的目录中。 然后您只需要确保所有 JAR 文件都部署在一起。

如果我没记错的话,默认的类路径是工作目录。 但是要指定类路径,您将在执行应用程序时使用-cp-classpath--class-path 如果需要,可以使用-p--module-path设置模块--module-path

脂肪罐

创建所谓的“fat”或“uber”JAR 文件。 这是一个 JAR 文件,不仅包含您自己的应用程序代码,还包含您应用程序的所有依赖项。 您可以为此配置jar任务,但简单地应用Gradle Shadow Plugin可能会更容易。

// Kotlin DSL
plugins {
    id("com.github.johnrengelman.shadow") version "<version>"
    // other plugins...
}

然后您将使用./gradlew shadowJar创建胖 JAR。 有关更多信息,请参阅用户指南。

自包含应用程序

使用jpackage类的工具创建一个独立的可执行文件。 该工具为您提供一个应用程序,其中包含所有代码嵌入的 JRE ,然后为您提供安装程序或本机可执行文件(例如 Windows 上的exe )。 这是jpackage用户指南 有一些 Gradle 插件可以让使用来自 Gradle 的jpackage变得更容易,比如The Badass JLink Plugin

注意jpackage是在 Java 14 中添加的,并且一直在孵化到 Java 16。还要注意jpackage不能“跨包”。 也就是说,如果您在 Windows 上构建应用程序,那么您只能为 Windows 创建安装程序/可执行文件; MacOS 和 Linux 也一样。 如果您需要为多个平台打包,那么您需要访问每个平台。


JavaFX

由于您已使用 JavaFX 标记了此问题,因此我想提醒您注意。 但是,如果您不使用 JavaFX 9+,那么这与您无关。

从技术上讲,JavaFX 仅支持作为命名模块加载。 这意味着它需要通过--module-path或通过将其包含在由jlink / jpackage构建的自定义运行时映像中来放置在模块路径上。 从 JavaFX 16 开始,如果从未命名的模块(即类路径)加载 JavaFX,则会发出警告。

可执行 JAR 文件放置在类路径中。 这包括胖 JAR。 如果您没有使用包含 JavaFX 的 JDK——这意味着您在 JavaFX 依赖项中有 Gradle 拉取——那么 JavaFX 将包含在您的胖 JAR 中并放置在类路径中。 现在,尽管不受支持并且现在发出警告,但如果 JavaFX 在类路径上,目前似乎没有任何问题。 除了一个警告:您的主类不能是javafx.application.Application的子类。 您必须创建一个单独的主类来简单地启动 JavaFX。

因此,我强烈建议使用jpackage来部署 JavaFX 应用程序。 您可能还想阅读此问答

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM