JavaFX+Spring Boot模块化Jar运行时YML文件无法检测问题
问题概述
- 模块化JavaFX + Spring Boot项目(含
Module-info.java)在IntelliJ社区版中运行正常,但打包为可执行模块化Jar后,YML/Properties配置文件无法被Spring Boot检测到(解压Jar可见文件存在) - 现有可行方案(
Copy to the output directory and link via manifest)虽能运行,但会解压所有依赖,导致Jar体积过大
环境配置
- JDK:Amazon Corretto 21
- JavaFX:21
- Spring Boot:3.2.0
控制台错误日志
Standard Commons Logging discovery in action with spring-jcl: please remove commons-logging.jar from classpath in order to avoid potential conflicts
:: Spring Boot :: (v3.2.0)
14:00:32.070 [JavaFX-Launcher] INFO org.springframework.boot.SpringApplication -- Starting application using Java 21.0.2 with PID 10608 (started by person in some/folder)
14:00:32.076 [JavaFX-Launcher] INFO org.springframework.boot.SpringApplication -- No active profile set, falling back to 1 default profile: "default"
解决方案
1. 修正Module-info.java的资源访问权限
模块化环境下,Spring Boot无法自动读取未开放/导出的模块内资源,需显式配置:
module your.module.name { // 开放配置文件所在包,允许Spring Boot类加载器访问 opens your.package.config to org.springframework.boot; // 若配置文件在根资源目录,开放模块根路径 opens to org.springframework.boot; // 导出业务包(按需) exports your.package.service to org.springframework.boot; opens your.package.service to org.springframework.boot, javafx.fxml; // 必要的模块依赖声明 requires javafx.controls; requires javafx.fxml; requires org.springframework.boot; requires org.springframework.boot.autoconfigure; }
2. 调整Spring Boot打包插件配置
Maven(pom.xml)
确保资源被正确打包进模块化Jar,并指定JavaFX启动类:
<build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> <version>3.2.0</version> <configuration> <mainClass>your.package.JavaFxSpringBootApplication</mainClass> <manifest> <attributes> <ModuleMainClass>your.module.name/your.package.JavaFxSpringBootApplication</ModuleMainClass> </attributes> </manifest> <includes> <include> <groupId>*</groupId> <artifactId>*</artifactId> </include> </includes> </configuration> <executions> <execution> <goals> <goal>repackage</goal> </goals> </execution> </executions> </plugin> <plugin> <groupId>org.openjfx</groupId> <artifactId>javafx-maven-plugin</artifactId> <version>0.0.8</version> <configuration> <mainClass>your.package.JavaFxSpringBootApplication</mainClass> <modules> <module>your.module.name</module> </modules> </configuration> </plugin> </plugins> </build>
Gradle(build.gradle)
plugins { id 'org.springframework.boot' version '3.2.0' id 'io.spring.dependency-management' version '1.1.4' id 'java' id 'org.openjfx.javafxplugin' version '0.0.13' } javafx { version = '21' modules = ['javafx.controls', 'javafx.fxml'] } springBoot { mainClass = 'your.package.JavaFxSpringBootApplication' } tasks.named('bootJar') { duplicatesStrategy = DuplicatesStrategy.INCLUDE manifest { attributes 'ModuleMainClass': 'your.module.name/your.package.JavaFxSpringBootApplication' } }
3. 显式指定Spring Boot资源位置
在JavaFX启动类中强制指定配置文件路径,确保Spring能定位到资源:
@SpringBootApplication public class JavaFxSpringBootApplication extends Application { public static void main(String[] args) { // 显式指定配置文件位置 System.setProperty("spring.config.location", "classpath:/application.yml"); launch(args); } @Override public void start(Stage stage) throws Exception { ConfigurableApplicationContext context = SpringApplication.run( JavaFxSpringBootApplication.class, getParameters().getRaw().toArray(new String[0]) ); // 后续JavaFX界面加载逻辑 } }
4. 验证打包后资源路径
解压生成的Jar文件,确认application.yml位于BOOT-INF/classes/目录下(Spring Boot标准资源路径)。若不在,调整Maven/Gradle的资源复制规则,确保src/main/resources下的文件被正确打包。
内容的提问来源于stack exchange,提问作者Nec-divinos

