运行Jar包时触发ClassPathResource FileNotFoundException,求助排查
Jar包中读取资源文件失败的问题分析与解决
这个问题我碰到过好多次啦,核心原因很明确——你混淆了本地文件系统里的资源和Jar包内的资源的访问方式!
为什么本地运行正常,打包后报错?
在IntelliJ中运行项目时,你的abc/myfile是实实在在存放在本地磁盘的目录里的,classPathResource.getFile()能直接拿到对应的File对象,自然没问题。但打包成Jar后,这个文件被嵌入到了Jar归档文件内部,它不再是文件系统里的独立文件,而是Jar里的一个"条目",这时候getFile()方法就失效了——因为File类只能指向文件系统中的实体,根本识别不了Jar包内的资源。
解决方法:用输入流读取Jar内资源
直接放弃getFile(),改用输入流来读取资源,这是处理归档文件内资源的标准姿势,给你两种可行的写法:
写法一:基于Spring的ClassPathResource获取输入流
String readFile(String schemaFileName) throws IOException { ClassPathResource classPathResource = new ClassPathResource("abc/" + schemaFileName); // 用getInputStream()替代getFile() try (InputStream inputStream = classPathResource.getInputStream()) { // 读取输入流并转换为字符串 return new String(inputStream.readAllBytes(), StandardCharsets.UTF_8); } }
写法二:用类加载器直接获取资源流
如果你的代码不依赖Spring,也可以用JDK原生的类加载器方法:
String readFile(String schemaFileName) throws IOException { String resourcePath = "abc/" + schemaFileName; try (InputStream inputStream = getClass().getClassLoader().getResourceAsStream(resourcePath)) { if (inputStream == null) { throw new FileNotFoundException("找不到资源文件: " + resourcePath); } return new String(inputStream.readAllBytes(), StandardCharsets.UTF_8); } }
额外提醒
- 永远记住:当资源可能被打包到Jar/War等归档文件时,绝对不要用
getFile()方法,输入流是唯一可靠的访问方式。 - 一定要检查输入流是否为null,避免空指针异常,同时抛出明确的异常信息,方便排查问题。
内容的提问来源于stack exchange,提问作者Ganesh Satpute
相关产品推荐
相关产品推荐

