需求
设在一个Spring Boot项目中,static
目录的结构如下:
1 | static/ |
现在想拿到the_dir
目录中的文件列表(不含子目录),读取每个文件的内容,并计算每个文件相对于static
目录的路径(即浏览器访问路径)。
获取文件列表
思路一:操作文件系统(不可行)
通过Spring的工具类ResourceUtils.getFile("classpath:static/the_dir")
拿到the_dir
目录的File
对象,再通过theDir.listFiles()
拿到文件列表,文件列表中可以通过file.isDirectory()
判断是普通文件还是目录。
结果:IDE中开发、Maven测试阶段都正常,但打包后运行jar包时报错:
1 | Caused by: java.io.FileNotFoundException: class path resource [static/the_dir] cannot be resolved to absolute file path because it does not reside in the file system: jar:nested:/C:/.../target/xxx.jar/!BOOT-INF/classes/!/static/the_dir |
原因:运行jar包时,static
目录及其下属各文件都在jar包中,而不在文件系统上,所以ResourceUtils
抛出了FileNotFoundException
异常。即,不能按文件系统的方式用Java文件API去操作。
思路二:操作资源(可行)
查询Spring Framework的文档可知,Spring抽象了一个称为**“资源(Resource)”**的概念,资源既可以是文件系统中的文件,也可以是jar包中的文件。
通过资源解析器org.springframework.core.io.support.PathMatchingResourcePatternResolver
,可以拿到符合指定路径模式的资源列表(相当于文件列表)。
1 | PathMatchingResourcePatternResolver resolver = new PathMatchingResourcePatternResolver(); |
每个资源可以通过resource.isReadable()
(是否可读)判断是普通文件还是普通,true
表示是普通文件,false
表示是目录。
读取文件内容
Spring Boot 3可直接通过resource.getContentAsString(StandardCharsets.UTF-8)
读取文件内容,Spring Boot 2则需要通过resource.getInputStream()
获取输入流来读取文件内容。
计算访问路径
资源可以通过resource.isFile()
判断是否在文件系统中,进而通过不同的方式拿到路径。
每个文件的路径去掉static
目录的路径,就是该文件相对于static
目录的访问路径。
1 | Resource staticDirectoryResource = resolver.getResource("classpath:static"); |