You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用Leiningen为Java 17+JavaFX 17的Clojure项目构建可运行Uberjar

解决方案

你遇到的问题是JavaFX 11+版本模块化设计导致的打包限制:当主类直接继承javafx.application.Application时,Java会强制要求JavaFX组件位于模块路径而非类路径下,而常规uberjar是将所有依赖放到类路径加载,因此触发运行时缺失的报错。Leiningen完全可以实现符合需求的打包,调整配置和代码即可。

1. 修改project.clj配置

调整依赖项和打包规则,补充JavaFX各平台原生组件、排除模块声明文件冲突:

(defproject sutest "0.1.0-SNAPSHOT"
  :description "Test for including JavaFX components in uberjar"
  :dependencies [[org.clojure/clojure "1.10.3"]
                 [org.openjfx/javafx-base "17.0.1"]
                 [org.openjfx/javafx-graphics "17.0.1"]
                 [org.openjfx/javafx-controls "17.0.1"]
                 ;; 按需追加对应平台的分类器依赖,不需要跨平台运行可只保留当前使用的平台
                 [org.openjfx/javafx-base "17.0.1" :classifier "win"]
                 [org.openjfx/javafx-base "17.0.1" :classifier "mac"]
                 [org.openjfx/javafx-base "17.0.1" :classifier "linux"]
                 [org.openjfx/javafx-graphics "17.0.1" :classifier "win"]
                 [org.openjfx/javafx-graphics "17.0.1" :classifier "mac"]
                 [org.openjfx/javafx-graphics "17.0.1" :classifier "linux"]
                 [org.openjfx/javafx-controls "17.0.1" :classifier "win"]
                 [org.openjfx/javafx-controls "17.0.1" :classifier "mac"]
                 [org.openjfx/javafx-controls "17.0.1" :classifier "linux"]]
  :aot :all
  :main sutest.core
  ;; 排除各JavaFX依赖中的模块声明文件,避免打包时覆盖冲突
  :uberjar-exclusions [#"module-info\.class"])

2. 调整代码启动逻辑

不要将主类设置为Application的子类,通过普通主类调用启动方法绕开模块路径检查:

(ns sutest.core
  (:import
    [javafx.application Application Platform]
    [javafx.event EventHandler]
    [javafx.geometry Insets Pos]
    [javafx.scene Scene]
    [javafx.scene.control Button Label]
    [javafx.scene.layout VBox]))

;; 单独实现Application逻辑,不作为主类
(def app-instance
  (proxy [Application] []
    (start [stage]
      (let [hiLbl (Label. "Hello World!")
            exitBtn (Button. "Exit")
            root (VBox. 12.0)]
        (.setOnAction exitBtn (reify EventHandler (handle [_ _]
                                                    (Platform/exit))))
        (.setPadding root (Insets. 0 10 0 10))
        (.addAll (.getChildren root) [hiLbl exitBtn])
        (.setAlignment root Pos/CENTER)
        (.setScene stage (Scene. root 250 150)))
      (.show stage))))

(defn -main [& args]
  (Application/launch (.getClass app-instance) args))

3. 打包运行

修改完成后执行lein uberjar,生成的jar包可直接通过以下命令运行:

java -jar target/sutest-0.1.0-SNAPSHOT-standalone.jar

其他构建工具说明

  • tools.deps、boot同样可以实现该需求,核心逻辑和上述方案一致:补充JavaFX对应平台的分类器依赖、排除模块声明文件、使用非Application子类作为启动入口。
  • Gluon官方针对Java项目的打包教程逻辑可以直接平移到Clojure生态,仅需将Maven/Gradle的配置对应转换为所用构建工具的配置规则即可。

内容的提问来源于stack exchange,提问作者clartaq

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.28 06:36:04