我们一般都习惯把一些资源文件放到 /src/main/resources
中,然后在程序中用一些类库读取
准备一个文件在resources目录下
/src/main/resources
|-foo.txt
文件的内容
妖姬脸似花含露,玉树流光照后庭。
使用 ResourceUtils 读取
@GetMapping("/txt1")
public Object index () throws IOException {
try {
// 通过ResourceUtils获取classpath下的foo.txt文件,读取为 File
File file = ResourceUtils.getFile("classpath:foo.txt");
try (InputStream inputStream = new FileInputStream(file)){
// 读取到字节数组
byte[] content = StreamUtils.copyToByteArray(inputStream);
// 响应给客户端
return ResponseEntity.status(HttpStatus.OK).header("Content-Type", "text/plain; charset=utf-8").body(content);
}
} catch (IOException e) {
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).header("Content-Type", "text/plain; charset=utf-8").body(e.getMessage());
}
}
这是大家用的最多的工具类,它很方便,可以直接把classpath
下的文件读取为File
对象,在IDE中启动项目,访问,一切OK
但是一旦打包为jar文件,独立启动,访问的时候,这个方法就抛出异常
class path resource [foo.txt] cannot be resolved to absolute file path because it does not reside in the file system: jar:file:/D:/eclipse/eclipse-jee-2020-12-R-win32-x86_64/project/springboot-demo/target/springboot-demo.jar!/BOOT-INF/classes!/foo.txt
打包后独立执行的jar文件,已经是一个独立的文件(压缩文件)了。ResourceUtils
尝试从classpath
路径下加载指定的文件,封装为File
,但是foo.txt
文件已经是这个文件的一部分。没办法把一个文件的一部分再封装成一个File
对象。
使用 ClassPathResource 读取
@GetMapping("/txt2")
public Object index1 () throws IOException {
try {
ClassPathResource classPathResource = new ClassPathResource("foo.txt");
try(InputStream inputStream = classPathResource.getInputStream()){
byte[] content = StreamUtils.copyToByteArray(inputStream);
return ResponseEntity.status(HttpStatus.OK).header("Content-Type", "text/plain; charset=utf-8").body(content);
}
} catch (IOException e) {
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).header("Content-Type", "text/plain; charset=utf-8").body(e.getMessage());
}
}
看类名就知道,它就是专门读取classpath
下资源的工具类。它并不会把资源封装为File
对象,而是,返回Inputstream
,用于读取内容。不论是在IDE中,还是打包为jar执行,都可以成功的读取到文件内容。
必选要封装为File对象
有些时候,需要调用第三方的一些类库,人家给的参数就必选是File
,可以考虑用ClassPathResource
读取资源数据,复制到本地磁盘,返回封装本地磁盘的资源为File
对象去调用第三方的类库。