Springboot项目打成jar包后获取resources目录下的模板文件失败

在使用模板文件进行文件相关操作时,使用IDEA本地测试没有任何问题,打成jar包后部署,发现不能正常读取resources目录下template文件夹下的模板文件,出现类似 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 的问题。

SpringBoot项目构建成jar运行后,如何正确读取resource下的文件?

不管你使用的是SpringBoot 1.x还是SpringBoot2.x,在Dev环境中使用eclipse、IEAD、STS等IDE工具,进行resource目录下文件的获取,简单的采用@Value注解的形式就可以得到,文件读取的主知一般情况下也是没有问题的,比如

File file = ResourceUtils.getFile("classpath:exceltmp/template_export.xls");

Resource下的文件是存在于jar这个文件里面,在磁盘上是没有真实路径存在的,它其实是位于jar内部的一个路径。所以通过ResourceUtils.getFile或者this.getClass().getResource(“”)方法无法正确获取文件。

有一种比较偷懒的做法:将文档放在项目外,应用可以读取到的一个固定目录。按正常的方式读取即可,但可维护性比较差,很容易被误操作丢失。

文本文件读取

这种情况下可以采用流的方式来读取文件,拿到文件流再进行相关的操作。如果你使用Spring框架的话,可以采用ClassPathResource来读取文件流,将文件读取成字符串才进行二次操作,比较适用于文本文件,如properties,txt,csv,SQL,json等,代码参考:

String data = "";
ClassPathResource cpr = new ClassPathResource("static/file.txt");
try {
    byte[] bdata = FileCopyUtils.copyToByteArray(cpr.getInputStream());
    data = new String(bdata, StandardCharsets.UTF_8);
} catch (IOException e) {
    LOG.warn("IOException", e);
}

提供一个工具类来帮助大家读取文件:

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.stream.Collectors;
import org.springframework.core.io.ClassPathResource;
public final class ClassPathResourceReader {
    /**
     * path:文件路径
     * @since JDK 1.8
     */
    private final String path;
    /**
     * content:文件内容
     * @since JDK 1.6
     */
    private String content;
    public ClassPathResourceReader(String path) {
        this.path = path;
    }
    public String getContent() {
        if (content == null) {
            try {
                ClassPathResource resource = new ClassPathResource(path);
                BufferedReader reader = new BufferedReader(new InputStreamReader(resource.getInputStream()));
                content = reader.lines().collect(Collectors.joining("\n"));
                reader.close();
            } catch (IOException ex) {
                throw new RuntimeException(ex);
            }
        }
        return content;
    }
}

使用方式也非常简单:

String content = new ClassPathResourceReader("log4j.properties").getContent();

非文本文件读取

更多的情况是读取非文本文件,比如xls,还是希望拿到一个文件,再去解析使用。参考代码如下:

String templatePath = "exceltmp/template_export.xls"
ClassPathResource classPathResource = new ClassPathResource(templatePath );
InputStream inputStream = classPathResource.getInputStream();
//生成目标文件
String prefix = "template_copy_" + UUID.randomUUID();
String suffix = templatePath .surbstring(templatePath.lastIndexOf("."))
File newFile = File.createTempFile(prefix, suffix);
try {
    FileUtils.copyInputStreamToFile(inputStream, newFile);
} finally {
    IOUtils.closeQuietly(inputStream);
}

拿到目标文件后,再按照正常的取法如ResourceUtils.getFile,读取即可。
最后别忘了删除临时文件newFile。

你可能感兴趣的:(JAVA,spring,boot,jar,java)