本文概览:解决spring boot读取resources下面文件的方式。
1 问题描述
假设在spring boot 项目中我们需要读取resources下面的input.txt文件。
如果代码中通过如下方式直接读取,那么此时会报错
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
@RequestMapping("/readFile") @ResponseBody public ResponseDemo readFile() { ResponseDemo demo = new ResponseDemo(); Properties prop = new Properties(); try { // 相对路径 String filePath = getClass().getResource("/").getPath()+"input/input.txt"; FileInputStream in = new FileInputStream(filePath); prop.load(in); demo.setMessage(prop.getProperty("key")); } catch (Exception e) { demo.setMessage(e.getMessage()); } demo.setResultCode("000"); return demo; } |
报错信息为:
“class path resource [input/input.txt] cannot be resolved to absolute file path because it does not reside in the file system: jar:
file:/Users/heartthinkdo/Project/mycode/template/springbootTemplateLocalFile/target/springbootTemplate-1.0-SNAPSHOT.jar!/BOOT-INF/classes!/input/input.txt”
在:https://stackoverflow.com/questions/36371748/spring-boot-access-static-resources-missing-scr-main-resources中查到一个方法,即使用ClassPathResource#getFile如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
@RequestMapping("/readFile") @ResponseBody public ResponseDemo readFile() { ResponseDemo demo = new ResponseDemo(); Properties prop = new Properties(); try { // 使用ClassPathResource#getFile File file = new ClassPathResource("input/input.txt").getFile(); FileInputStream in = new FileInputStream(file.getPath()); prop.load(in); demo.setMessage(prop.getProperty("key")); } catch (Exception e) { demo.setMessage(e.getMessage()); } demo.setResultCode("000"); return demo; } |
但是有个问题:在Intellij Idea中直接run 可以正常读取文件,但打成jar包以java -jar运行则还是报异常:
“class path resource [input/input.txt] cannot be resolved to absolute file path because it does not reside in the file system: jar:file:/Users/heartthinkdo/Project/mycode/template/springbootTemplateLocalFile/target/springbootTemplate-1.0-SNAPSHOT.jar!/BOOT-INF/classes!/input/input.txt”
2解决方案
方案1: 使用ClassPathResource#getInputstream
使用使用ClassPathResource#getFile在执行jar时还是会报错,这是什么原因呢,如何解决?这是因为spring boot打包成jar之后无法获取respurce下面的文件,解决方案可以参考spring boot的作者回复:
https://stackoverflow.com/questions/25869428/classpath-resource-not-found-when-running-as-jar
1 |
resource.getFile() expects the resource itself to be available on the file system, i.e. it can't be nested inside a jar file. This is why it works when you run your application in STS but doesn't work once you've built your application and run it from the executable jar. Rather than using getFile() to access the resource's contents, <strong><em>I'd recommend using <span style="color: #ff0000;">getInputStream() instead</span></em></strong>. That'll allow you to read the resource's content regardless of where it's located. |
对应的代码如下:
1 2 |
ClassPathResource classPathResource = new ClassPathResource("input/input.txt"); InputStream inputStream = classPathResource.getInputStream(); |
方案2: 文件系统的全路径
通过maven-assembly-plugin将input.txt打包在本地文件系统中,而不是jar中。假设服务根目录为”/Users/work/springbootTemplateLocalFile”,使用maven-assembly-plugin打包时,将input.txt保存在此目录下conf目录下面:
- 需要在将resouces下面input.input移动到项目的input/input.txt
- 通过assemble.xml配置
1 2 3 4 5 6 7 8 9 |
<fileSet> <!-- 项目中 input.txt所在目录。--> <directory>./input/input.txt</directory> <!-- 打包之后 input.txt所在目录--> <outputDirectory>./conf</outputDirectory> <includes> <include>**</include> </includes> </fileSet> |
通过如下代码直接读取
1 |
FileInputStream in = new FileInputStream("/Users/work/springbootTemplateLocalFile/config/input/input.txt"); |
参考文献:
Classpath resource not found when running as jar:https://stackoverflow.com/questions/25869428/classpath-resource-not-found-when-running-as-jar
Java: Load file from classpath in Spring Boot :https://smarterco.de/java-load-file-from-classpath-in-spring-boot/
springboot打包成jar后获取classpath下文件失败:https://blog.csdn.net/qq_33352259/article/details/81567003