欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

EasyPoi 模板导出报空指针问题处理

程序员文章站 2022-03-15 23:21:41
...

一、前言

下图代码是SpringBoot项目controller层中的easypoi模板导出功能。在正常的开发测试过程中,并不会出现问题,但是当我们将其打成jar包放到Linux服务器上时,就会出现NPE(空指针异常),异常为第51行中的Excel模板找不到。

主要原因有两点:

  1. Linux和Window文件系统环境不一致。
  2. springBoot项目打jar包后文件资源加载方式不同,打包后Spring试图访问文件系统路径,但无法访问jar中的路径。 

Spring作者本人回答如下图,

原文:https://*.com/questions/25869428/classpath-resource-not-found-when-running-as-jar

导出功能 

EasyPoi 模板导出报空指针问题处理

Spring作者回答(google翻译)

EasyPoi 模板导出报空指针问题处理

 

二、解决方案 

可以使用 resource.getInputStream() 获取模板的文档流,重写到tomcat容器中并生成新的模板路径,按新的路径,导出excel即可。

EasyPoi 模板导出报空指针问题处理

ExcelExportUtils.convertTemplatePath( )  方法代码如下:

/**
 * @Author gmd
 * @Description Excel导出方法
 */
public class ExcelExportUtils {
    /**
     * 模板路径处理,避免出现NPE
     * windows和linux系统不同,且SpringBoot的文件加载方式已有不同,不能简单的使用相对路径
     * @param path excel模板的相对路径
     * @return 重写后的模板路径
     */
    public static String convertTemplatePath(String path) {
        // 如果是windows则直接返回
        if (System.getProperties().getProperty("os.name").contains("Windows")) {
            return path;
        }

        Resource resource = new ClassPathResource(path);
        FileOutputStream fileOutputStream = null;
        // 将模版文件写入到tomcat临时目录
        String folder = System.getProperty("catalina.home");
        File tempFile = new File(folder + File.separator + path);
        // 文件存在时不再写入
        if (tempFile.exists()) {
            return tempFile.getPath();
        }
        File parentFile = tempFile.getParentFile();
        // 判断父文件夹是否存在
        if (!parentFile.exists()) {
            parentFile.mkdirs();
        }
        try {
            BufferedInputStream inputStream = new BufferedInputStream(resource.getInputStream());
            fileOutputStream = new FileOutputStream(tempFile);
            byte[] buffer = new byte[10240];
            int len = 0;
            while ((len = inputStream.read(buffer)) != -1) {
                fileOutputStream.write(buffer, 0, len);
            }
        } catch (IOException e) {
            e.printStackTrace();

        } finally {
            if (fileOutputStream != null) {
                try {
                    fileOutputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        return tempFile.getPath();
    }

}

Excel temp2.xlsx 模板

EasyPoi 模板导出报空指针问题处理

前端导出代码

<!--HTML代码-->
<button type="button" id="excelOutBtn" class="btn btn-sm bg-orange">
    <i class="fa fa-cloud-upload fa-btn"></i> 导出
</button>

<!--JS-->
// 导出
$("#excelOutBtn").click(function () {
    window.location.href = "${basePath}/aaa/bbb/ccc?id=" + $("#id").val();
});

 

三、后记

至此,通过 resource.getInputStream() 方法我们已经解决了NPE问题。但是存在另一个明显的性能问题,即上述方法 需要生成新的excel模板,重写磁盘,耗时且低效。

而更好的解决方案是通过FreeMarker的excel模板来导出数据。具体方法见本人另一篇博客:

https://blog.csdn.net/qq_41057885/article/details/109682412