目录
问题
在Springboot项目中,需要从resources中读取图片文件,在idea中运行得没问题,但部署到linux运行的时候,却报了以下错误,如下图:
分析问题
一 :项目结构和代码展示
项目结构,如下图:
代码:
二 : 问题分析
通过上面代码看,好像没看出什么问题。经过自己查找资料和翻阅博客,发现要解决这个问题,需要很庞大的知识体系才可以弄懂,而我也只知个大概,下面把我理解的写下,希望能帮助到你。
1.猜测是不是文件路径的问题
首先,需要知道类加载相关知识,在JVM中,类都是懒加载的,当我们需要用到的时候才会被加载进JVM中,而在springboot中,类加载器是从classPath下,去加载文件。此时,在springboot中如果我们需要加载文件,可以通过以下3种方式:
- Class.getClassLoader().getResource(String path)
- Class.getResource(String path)
-
new ClassPathResource(String path)
对于Class.getClassLoader().getResource(String path)和new ClassPathResource(String path)来说,他们已经是从classPath下读取文件,如果再加"/"开头,例如:"/static/img/template.png"就会报错。而对于 Class.getResource(String path)来说,可以加"/"开头,也可以不加"/"开头,它底层还是调到Class.getClassLoader().getResource(String path)去,但如果path不加"/",例如"static/img/template.png",则代表是相对路径,表示相对于当前运行这行代码的类,此时会加上 包名+static/img/template.png。而加上"/",也是从classPath下读取文件。
而我上面代码例子是通过以下方式加载,看起来是没有问题,不管是在idea中运行,还是达成jar放在linux中运行,都能够从项目中,找到这个文件,那代表不是文件路径的问题。
Test1.class.getClassLoader().getResource("static/img/template.png")
2. 猜测是不是getPath()获取的path有问题
此时修改代码如下,打包成jar包,进行测试,代码如下:
运行结果,如下:
结果打印出来了,并且可以看到有报错信息,就是开头所说的问题。
为了更清晰的观看和理解,我也把在idea中运行的结果贴出来,如下:
而在idea运行的代码,却没有任何报错信息。
通过 path对比,可以明显猜到,问题应该是出这路径和文件定位方面。这里有篇文章解释了大概问题,点击跳转可以观看。大概说了new File(),只能定位到文件系统,而对于像jar这些压缩包却无法使用,此时推荐使用getInputStream()流的方式来读取文件。
3.修改代码,继续测试,代码如下:
测试结果正常 ,可以正常读取。用ClassPathResource也行,也可以正常运行。推荐大家尽量都用ClassPathResource来读取文件,而对于new File()来说,代码中尽量少用,它可能在window中能正常运行,在Linux中可能就会运行异常了。
4.思考
上面打印出path的路径的时候,发现有很多使用!/分隔开的路径,这个与springboot内部扩展出来的URL协议有关,有兴趣的可以点击 链接跳转查看相关内容。
path路径打印结果: