本文共 5476 字,大约阅读时间需要 18 分钟。
在项目B端中,经常会有Excel表格导入导出功能,java中的Apache POI 是一个针对Excel功能非常好的操作库。关于POI网上也有很多的文章,这里主要说一下阿里的EasyExcel实现导表功能;
之前我们项目中的Excel导出功能使用的是poi userModel模式,相信在过去的一段时间中,应该也有不少的项目采用的是这种模式,此种模式的解析速度很快,但是弊端也很大,如果表数据量一旦很大内存就很容易爆掉了。因为userModel的数据解析类似于Dom方式解析,将数据全部加载到内存,然后生成Dom树的过程。
注意:userModel是将所有数据全部加载到内存中进行解析,所以他的解析速度快,内存消耗非常大!但是这也是可能导致OOM(内存溢出)的原因。
导表OOM的解决方案:
1.将数据量减小,比如分批次导出(原来你导的一周的数据分成按天导出,数据量就能小很多)
2.前端js导表
3.阿里EasyExcel
这里着重谈一下阿里EasyExcel工具类:
导表的效果如图:
使用easyExcel首先导入以下依赖:
<!-- https://mvnrepository.com/artifact/com.alibaba/easyexcel -->
<dependency> <groupId>com.alibaba</groupId> <artifactId>easyexcel</artifactId> <version>2.1.6</version> </dependency>这里说明一下:上面表格样式最终的呈现需要在实体类上使用部分注解配合,可以通过下面的注解来设置行高列宽,设置标题名和主标题名。
下面是我在项目中针对导表使用到的工具类(因为项目中只用到导出暂时没有表格导入,所以这里我就没写导入了)
/** * @Author: LQ * @Date: 2019/9/25 16:17 */public class EasyExcelUtils { /** * 导出Excel(一个sheet) * * @param response HttpServletResponse * @param list 数据list * @param fileName 导出的文件名 * @param sheetName 导入文件的sheet名 * @param clazz 实体类 */ public staticvoid writeExcel(HttpServletResponse response, List list, String fileName, String sheetName, Class clazz) { OutputStream outputStream = getOutputStream(response, fileName); ExcelWriter excelWriter = EasyExcel.write(outputStream, clazz).build(); WriteSheet writeSheet = EasyExcel.writerSheet(sheetName).build(); excelWriter.write(list, writeSheet); excelWriter.finish(); } public static void writeStyleExcel(List list, String fileName, String sheetName, Class clazz) { // 头的策略 WriteCellStyle headWriteCellStyle = new WriteCellStyle(); // 背景设置为红色 headWriteCellStyle.setFillForegroundColor(IndexedColors.YELLOW.getIndex()); headWriteCellStyle.setHorizontalAlignment(HorizontalAlignment.CENTER); WriteFont headWriteFont = new WriteFont(); headWriteFont.setFontHeightInPoints((short) 10); headWriteFont.setFontName("宋体"); headWriteCellStyle.setWriteFont(headWriteFont); // 内容的策略 WriteCellStyle contentWriteCellStyle = new WriteCellStyle(); contentWriteCellStyle.setHorizontalAlignment(HorizontalAlignment.CENTER); contentWriteCellStyle.setBorderBottom(BorderStyle.THIN); contentWriteCellStyle.setBorderLeft(BorderStyle.THIN); contentWriteCellStyle.setBorderRight(BorderStyle.THIN); contentWriteCellStyle.setBorderTop(BorderStyle.THIN); // 这里需要指定 FillPatternType 为FillPatternType.SOLID_FOREGROUND 不然无法显示背景颜色.头默认了 FillPatternType所以可以不指定 contentWriteCellStyle.setFillPatternType(FillPatternType.SOLID_FOREGROUND); // 背景绿色 contentWriteCellStyle.setFillForegroundColor(IndexedColors.WHITE.getIndex()); WriteFont contentWriteFont = new WriteFont(); // 字体大小 contentWriteFont.setFontHeightInPoints((short) 10); contentWriteFont.setFontName("宋体"); contentWriteCellStyle.setWriteFont(contentWriteFont); // 这个策略是 头是头的样式 内容是内容的样式 其他的策略可以自己实现 HorizontalCellStyleStrategy horizontalCellStyleStrategy = new HorizontalCellStyleStrategy(headWriteCellStyle, contentWriteCellStyle); // 这里 需要指定写用哪个class去读,然后写到第一个sheet,名字为模板 然后文件流会自动关闭 EasyExcel.write(fileName, clazz).registerWriteHandler(horizontalCellStyleStrategy).sheet(sheetName) .doWrite(list); } /** * 导出Excel(带样式) * * @return */ public static void writeStyleExcel(HttpServletResponse response, List list, String fileName, String sheetName, Class clazz) { // 头的策略 WriteCellStyle headWriteCellStyle = new WriteCellStyle(); // 背景设置为红色 headWriteCellStyle.setFillForegroundColor(IndexedColors.YELLOW.getIndex()); headWriteCellStyle.setHorizontalAlignment(HorizontalAlignment.CENTER); WriteFont headWriteFont = new WriteFont(); headWriteFont.setFontHeightInPoints((short) 10); headWriteFont.setFontName("宋体"); headWriteCellStyle.setWriteFont(headWriteFont); // 内容的策略 WriteCellStyle contentWriteCellStyle = new WriteCellStyle(); contentWriteCellStyle.setHorizontalAlignment(HorizontalAlignment.CENTER); contentWriteCellStyle.setBorderBottom(BorderStyle.THIN); contentWriteCellStyle.setBorderLeft(BorderStyle.THIN); contentWriteCellStyle.setBorderRight(BorderStyle.THIN); contentWriteCellStyle.setBorderTop(BorderStyle.THIN); // 这里需要指定 FillPatternType 为FillPatternType.SOLID_FOREGROUND 不然无法显示背景颜色.头默认了 FillPatternType所以可以不指定 contentWriteCellStyle.setFillPatternType(FillPatternType.SOLID_FOREGROUND); // 背景绿色 contentWriteCellStyle.setFillForegroundColor(IndexedColors.WHITE.getIndex()); WriteFont contentWriteFont = new WriteFont(); // 字体大小 contentWriteFont.setFontHeightInPoints((short) 10); contentWriteFont.setFontName("宋体"); contentWriteCellStyle.setWriteFont(contentWriteFont); // 这个策略是 头是头的样式 内容是内容的样式 其他的策略可以自己实现 HorizontalCellStyleStrategy horizontalCellStyleStrategy = new HorizontalCellStyleStrategy(headWriteCellStyle, contentWriteCellStyle); OutputStream outputStream = getOutputStream(response, fileName); EasyExcel.write(outputStream, clazz).registerWriteHandler(horizontalCellStyleStrategy).sheet(sheetName).doWrite(list); } /** * 导出时生成OutputStream */ private static OutputStream getOutputStream(HttpServletResponse response, String fileName) { //创建本地文件 String filePath = fileName + ".xlsx"; File file = new File(filePath); try { if (!file.exists() || file.isDirectory()) { file.createNewFile(); } fileName = new String(filePath.getBytes(), "ISO-8859-1"); response.addHeader("Content-Disposition", "filename=" + fileName); return response.getOutputStream(); } catch (IOException e) { e.printStackTrace(); } return null; }}
除了阿里的easyexcel,在我另一篇文章: 中也有对excel导入导出的工具类封装,两种封装最终都能实现表格导出,封装方式有差别,可以根据自己的需要来使用。
转载地址:http://gchwi.baihongyu.com/