Spring Boot访问静态资源缺失scr/main/resources。

73

我正在开发一个Spring Boot应用程序。 我需要在启动时解析一个XML文件(countries.xml)。问题是我不知道该把它放在哪里才能访问它。 我的文件夹结构是

ProjectDirectory/src/main/java
ProjectDirectory/src/main/resources/countries.xml

我的第一个想法是将它放在src/main/resources中,但当我尝试创建File(countries.xml)时,我遇到了NPE,并且堆栈跟踪显示我的文件被查找在ProjectDirectory中(因此没有添加src/main/resources/)。 我尝试创建File(resources/countries.xml),路径看起来像ProjectDirectory/resources/countries.xml(所以再次没有添加src/main)。

我尝试添加这个但没有结果。

@Override
public void addResourceHandlers(final ResourceHandlerRegistry registry) {
    registry.addResourceHandler("/resources/**").addResourceLocations("/resources/");
    registry.setOrder(Ordered.HIGHEST_PRECEDENCE);
    super.addResourceHandlers(registry);
}

我知道我可以手动添加src/main/,但我想要了解为什么它不能按照预期工作。我还尝试了使用ResourceLoader的示例-但结果同样没有得到。

有人能否建议一下问题出在哪里?

更新: 供未来参考-在构建项目后,我遇到了访问文件的问题,所以我将File更改为InputStream。

InputStream is = new ClassPathResource("countries.xml").getInputStream();

你是否将此文件添加到web.xml或任何配置文件中,以告诉应用程序它的存在? - LearningPhase
仅仅将文件添加到文件夹并不能帮助应用程序扫描该文件。 - LearningPhase
我没有web.xml文件,我有一个基于Java的配置。你能否给我一些建议?或者你有任何示例吗?非常感谢! - lenach87
luboskrnac 给出了很好的建议。 - LearningPhase
针对基于注释的解决方案,请参阅:https://dev59.com/FFoV5IYBdhLWcg3wTdbN#39472514 - Fırat Küçük
这个对我有用的方法是使用File file = new File("sampleFile"),而SpringBoot从未在我的resources/static文件夹中找到它。感谢您的建议! - Robert Cadmire
8个回答

137

只需使用Spring的ClassPathResource类型即可。

File file = new ClassPathResource("countries.xml").getFile();
只要这个文件在类路径的某个位置,Spring就会找到它。在开发和测试过程中,它可以是src/main/resources。在生产环境中,它可以是当前运行的目录。 编辑:如果文件处于fat JAR中,则此方法无效。这种情况下,您需要使用:
InputStream is = new ClassPathResource("countries.xml").getInputStream();

1
非常感谢您!!这真的救了我!现在它按预期工作。 - lenach87
1
如何将此文件转换为JSONObject?(首先数据是JSONObject) - Mahdi
只是为了补充@luboskrnac的答案,还可以尝试使用File file = new ClassPathResource(".\countries.xml").getFile(); - Rahul Jawale
23
根据这个答案,resource.getFile()方法要求文件存在于实际的文件系统中,在JAR包中访问存储在src/main/resources下资源时,此解决方案无法工作。我已经通过一个简单的Spring Boot应用程序进行了确认。 - smeeb
3
谢谢。对我来说,使用 InputStream inputStream = new ClassPathResource("countries.xml").getInputStream(); 是可行的。 - TrueKojo
请根据smeeb的答案更新您的回答,这将拯救很多人的生命。 - Emdadul Sawon

9
在使用Spring Boot应用程序时,如果它以JAR包的形式部署,使用resource.getFile()获取类路径资源可能会很困难,我也遇到了同样的问题。可以使用Stream解决此问题,Stream可以查找放置在类路径中任何位置的所有资源。
以下是相应代码片段 -
ClassPathResource classPathResource = new ClassPathResource("fileName");
InputStream inputStream = classPathResource.getInputStream();
content = IOUtils.toString(inputStream);

1
它可以工作。 另外,请在您的SpringBoot应用程序中使用依赖项:<dependency> <groupId>commons-io</groupId> <artifactId>commons-io</artifactId> <version>2.6</version> </dependency> 旧的“toString”函数已被弃用。您必须使用新版本:IOUtils.toString(inputStream,"UTF-8") - AI_ROBOT

8
获取类路径中的文件:
Resource resource = new ClassPathResource("countries.xml");
File file = resource.getFile();

要在启动时读取文件,请使用@PostConstruct

@Configuration
public class ReadFileOnStartUp {

    @PostConstruct
    public void afterPropertiesSet() throws Exception {

        //Gets the XML file under src/main/resources folder
        Resource resource = new ClassPathResource("countries.xml");
        File file = resource.getFile();
        //Logic to read File.
    }
}

这是一个与Spring Boot应用程序启动时读取XML文件相关的小例子


谢谢你的回答!正如你和luboskrnac所建议的那样,第一部分救了我! - lenach87
@ElenaChubukina 请看这个例子。你说你需要在启动时解析XML... - Sanjay Rawat
谢谢!解析文件的部分没有问题(只有在类路径上找到文件的部分有点麻烦)- 我使用CommandLineRunner,对我来说很好用。 - lenach87

5

我使用Spring Boot,因此可以简单地使用:

File file = ResourceUtils.getFile("classpath:myfile.xml");

1
你可以使用以下代码从资源文件夹中读取字符串。
final Resource resource = new ClassPathResource("public.key");
String publicKey = null;
try {
     publicKey = new String(Files.readAllBytes(resource.getFile().toPath()), StandardCharsets.UTF_8);
} catch (IOException e) {
     e.printStackTrace();
}

1
您需要使用以下结构:

您需要使用以下结构

InputStream in = getClass().getResourceAsStream("/yourFile");

请注意,在文件名前面添加这个斜杠。

1
我使用Spring Boot,我对这个问题的解决方案是:
"src/main/resources/myfile.extension"

希望能对某些人有所帮助。

0
由于java.net.URL不能处理所有类型的低级资源,Spring引入了org.springframework.core.io.Resource。为了访问资源,我们可以使用@Value注释或ResourceLoader类。 @Autowired private ResourceLoader resourceLoader;
@Override public void run(String... args) throws Exception {
    Resource res = resourceLoader.getResource("classpath:thermopylae.txt");

    Map<String, Integer> words =  countWords.getWordsCount(res);

    for (String key : words.keySet()) {

        System.out.println(key + ": " + words.get(key));
    }
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接