如何用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
相关产品推荐
相关产品推荐

