前幾天在項(xiàng)目讀取resources目錄下的文件時(shí)碰到一個(gè)小坑,明明在本地是可以正常運(yùn)行的,但是一發(fā)到測(cè)試環(huán)境就報(bào)錯(cuò)了,說找不到文件,報(bào)錯(cuò)信息是:class path resource [xxxx] cannot be resolved to absolute file path because it does not reside in the file system: jar:file:xxxx.jar!/BOOT-INF/classes!xxxx。
看了半天代碼感覺沒有問題,于是懷疑是打成項(xiàng)目jar包后和原項(xiàng)目存在差異導(dǎo)致的。于是我把的項(xiàng)目打成jar包,在本地直接調(diào)試jar,果然發(fā)現(xiàn)問題所在。下面我將以一個(gè)自己的測(cè)試項(xiàng)目api-test替代原來的公司項(xiàng)目來講述一下排查過程。
一、項(xiàng)目代碼
GetResourceTest:
public class GetResourceTest {
public InputStream getResource1() throws IOException {
File file = new DefaultResourceLoader().getResource("/template/qiankuan.ftl").getFile();
return Files.newInputStream(file.toPath());
}
public InputStream getResource2() throws IOException {
ResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();
Resource[] resources = resolver.getResources("/template/qiankuan.ftl");
Resource resource = resources[0];
return resource.getInputStream();
}
}
TestController:
@RestController
@RequestMapping("/test")
public class TestController {
@GetMapping(value = "/getResource")
@ResponseBody
public void getResource() throws IOException {
GetResourceTest getResourceTest = new GetResourceTest();
getResourceTest.getResource1();
}
}
二、排查過程
1、首先使用Maven的install命令將項(xiàng)目打成jar包
命令執(zhí)行成功后再target目錄下就生成了jar包
2、在Termininal里cd到target目錄下,然后執(zhí)行下面的代碼,9992可以替換成其他端口
java -jar -Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=n,address=9992 api-test-1.0.0-SNAPSHOT.jar
執(zhí)行成功如下
3、添加遠(yuǎn)程調(diào)試
依次點(diǎn)擊菜單Run,點(diǎn)擊Edit Configurations,點(diǎn)擊+,點(diǎn)擊Remote JVM Debug,端口后改成剛剛設(shè)置的9992。
4、請(qǐng)求接口
請(qǐng)求測(cè)試接口,9991是項(xiàng)目原來的端口
127.0.0.1:9991/test/getResource
5、請(qǐng)求結(jié)果
請(qǐng)求果然報(bào)錯(cuò)了,報(bào)錯(cuò)和之前測(cè)試環(huán)境的報(bào)錯(cuò)一摸一樣。其實(shí)我們通過這個(gè)報(bào)錯(cuò)已經(jīng)可以大致上看出問題了。。。
6、斷點(diǎn)調(diào)試
在請(qǐng)求的入口打上斷點(diǎn)開始斷點(diǎn)調(diào)試
通過斷點(diǎn)調(diào)試也可以看到這個(gè)文件地址在原來的地址/template/qiankuan.ftl 前拼接了jar:file:/D:/Project/test/fhey-test/api-test/target/api-test-1.0.0-SNAPSHOT.jar!/BOOT-INF/classes!成為了jar:file:/D:/Project/test/fhey-test/api-test/target/api-test-1.0.0-SNAPSHOT.jar!/BOOT-INF/classes!/template/qiankuan.ftl。
然后在后面一段代碼中,resourceUrl.getProtocol()的返回結(jié)果是"jar"而不是"file", 被判定為不是文件然后拋出了一個(gè)FileNotFoundException異常。
三、解決方法
ResouceUtils.getFile()是專門用來加載非壓縮和Jar包文件類型的資源,所以它根本不會(huì)去嘗試加載Jar中的文件,要想加載Jar中的文件,只要用可以讀取jar中文件的方式加載即可,比如 可以采用ClassPathResource這種以流的形式讀取文件的方式或者PathMatchingResourcePatternResolver來讀取文件。文章來源:http://www.zghlxwxcb.cn/news/detail-515904.html
ClassPathResource classPathResource = new ClassPathResource("/template/qiankuan.ftl" );
InputStream inputStream = classPathResource.getInputStream();
或者文章來源地址http://www.zghlxwxcb.cn/news/detail-515904.html
ResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();
Resource[] resources = resolver.getResources("/template/qiankuan.ftl");
Resource resource = resources[0];
InputStream inputStream = resource.getInputStream();
到了這里,關(guān)于解決Springboot項(xiàng)目打成jar包后獲取resources目錄下的文件報(bào)錯(cuò)的問題的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!