EasyPoi 模板导出报空指针问题处理
程序员文章站
2022-03-15 23:21:41
...
一、前言
下图代码是SpringBoot项目controller层中的easypoi模板导出功能。在正常的开发测试过程中,并不会出现问题,但是当我们将其打成jar包放到Linux服务器上时,就会出现NPE(空指针异常),异常为第51行中的Excel模板找不到。
主要原因有两点:
- Linux和Window文件系统环境不一致。
- springBoot项目打jar包后文件资源加载方式不同,打包后Spring试图访问文件系统路径,但无法访问jar中的路径。
Spring作者本人回答如下图,
原文:https://*.com/questions/25869428/classpath-resource-not-found-when-running-as-jar
导出功能
Spring作者回答(google翻译)
二、解决方案
可以使用 resource.getInputStream() 获取模板的文档流,重写到tomcat容器中并生成新的模板路径,按新的路径,导出excel即可。
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 模板
前端导出代码
<!--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模板来导出数据。具体方法见本人另一篇博客:
上一篇: Python——while循环语句
下一篇: 也说AOP
推荐阅读