使用Java 9模块时,SpringBoot @Value+JavaFX为何需将文件放resources/static?
为什么带
module-info.java时Spring Boot的@Value加载资源必须放在resources/static下? 在使用module-info.java的情况下,通过Spring Boot的@Value注解加载XML等文件时,文件必须放置在resources/static/目标路径下,否则会抛出FileNotFoundException异常。目前找到的解决方案包括:删除module-info.java文件、移除org.openjfx.javafxplugin依赖、将XML文件移至resources/static/test/目录下,或是不使用@Value注解。但由于对Java模块机制理解有限,想知道这个问题产生的根源。
最小复现示例
项目结构
build.gradle src ├───main │ ├───java │ │ │ module-info.java │ │ │ │ │ └───com │ │ └───example │ │ App.java │ │ TestLoader.java │ │ │ └───resources │ │ application.properties │ │ │ ├───static │ │ └───test │ │ test.xml │ │ │ └───test │ test.xml │ └───test ├───java │ │ └───com │ │ └───example │ │ TestTest.java │ │ │ └───resources │ unused
注:unused是一个空文件,用于生成测试资源文件夹以避免报错。
Spring Boot应用类(App.java)
package com.example; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; @SpringBootApplication public class App { public static void main(String[] args) { SpringApplication.run(App.class, args); } }
资源加载类(TestLoader.java)
package com.example; import org.springframework.beans.factory.annotation.Value; import org.springframework.core.io.Resource; import org.springframework.stereotype.Component; import java.io.IOException; @Component public class TestLoader { private TestLoader(@Value("classpath:test/test.xml") Resource fxml) throws IOException { fxml.getInputStream(); } }
模块信息文件(module-info.java)
module com.example { requires spring.boot; requires spring.boot.autoconfigure; requires spring.context; requires spring.core; requires spring.beans; opens com.example to spring.beans, spring.context, spring.core; }
Gradle构建文件(build.gradle)
plugins { id 'java' id 'application' id 'org.openjfx.javafxplugin' version '0.0.13' id 'org.springframework.boot' version '3.4.2' id 'io.spring.dependency-management' version '1.1.7' } group 'com.example' version '0.0.1-SNAPSHOT' repositories { mavenCentral() } java { modularity.inferModulePath = true } application { mainModule = 'com.example' mainClass = 'com.example.App' } dependencies { implementation 'org.springframework.boot:spring-boot-starter' testImplementation('org.springframework.boot:spring-boot-starter-test'){ // https://github.com/spring-cloud/spring-cloud-deployer-kubernetes/issues/142 exclude group: "com.vaadin.external.google", module:"android-json" } testImplementation("org.junit.jupiter:junit-jupiter-api") testRuntimeOnly("org.junit.jupiter:junit-jupiter-engine") testRuntimeOnly 'org.junit.platform:junit-platform-launcher' } tasks.named('test') { useJUnitPlatform() }
测试类(TestTest.java)
package com.example; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; @SpringBootTest public class TestTest { @Autowired TestLoader loader; @Test public void test() { } }
内容的提问来源于stack exchange,提问作者LookingForFish
相关产品推荐
相关产品推荐

