您好,欢迎来到六九路网。
搜索
您的当前位置:首页easyExcel简明使用指南

easyExcel简明使用指南

来源:六九路网
easyExcel简明使⽤指南

easyExcel简介

Java领域解析、⽣成Excel⽐较有名的框架有Apache poi、jxl等。但他们都存在⼀个严重的问题就是⾮常的耗内存。如果你的系统并发量不⼤的话可能还⾏,但是⼀旦并发上来后⼀定会OOM或者JVM频繁的full gc。

easyExcel是阿⾥巴巴开源的⼀个excel处理框架,以使⽤简单、节省内存著称。

M内存1分钟内读取75M(46W⾏25列)的Excel(当然还有急速模式能更快,但是内存占⽤会在100M多⼀点)

easyExcel能⼤⼤减少占⽤内存的主要原因是在解析Excel时没有将⽂件数据⼀次性全部加载到内存中,⽽是从磁盘上⼀⾏⾏读取数据,逐个解析。下图是easyExcel和POI在解析Excel时的对⽐图。

easyExcel采⽤⼀⾏⼀⾏的解析模式,并将⼀⾏的解析结果以观察者的模式通知处理(AnalysisEventListener)。

上⾯简要介绍了easyExcel的特点和原理,关于easyExcel的其他问题可以先参考下这个。下⾯就通过代码来介绍下怎么使⽤easyExcel。快速使⽤指南

⽂件上传读取Excel

下⾯通过⼀个读取⽤户信息的列⼦来展⽰下怎么使⽤easyExcel。step1:创建⽤户信息类@Data

public class UserInfo extends BaseRowModel { @ExcelProperty(index = 0) private String name; @ExcelProperty(index = 1) private int age;

@ExcelProperty(index = 2) private String address;

}

step2:创建AnalysisEventListener⼦类/**

* 每解析⼀⾏会回调invoke()⽅法。

* 整个excel解析结束会执⾏doAfterAllAnalysed()⽅法 */

//有个很重要的点 不能被spring管理,要每次读取excel都要new。

//这边就会有⼀个问题:如果UserInfoDataListener中需要⽤到Spring中的主键怎么办?public class UserInfoDataListener extends AnalysisEventListener { Logger logger = LoggerFactory.getLogger(UserInfoDataListener.class);

//每次读取100条数据就进⾏保存操作

private static final int BATCH_COUNT = 100;

//由于每次读都是新new UserInfoDataListener的,所以这个list不会存在线程安全问题 List list = new ArrayList<>();

//这个组件是Spring中的组件,这边推荐两种⽅法注⼊这个组件

//第⼀种就是提供⼀个UserInfoDataListener的构造⽅法,这个⽅法提供⼀个参数是UserInfoDataListener类型 //另外⼀种⽅法就是将 UserInfoDataListener 这个类定义成 UserService 实现类的内部类(推荐这种⽅式) //private UserService userService;

@Override

public void invoke(UserInfo data, AnalysisContext analysisContext) { logger.info(\"解析到⼀条数据:{}\ list.add(data);

if (list.size() >= BATCH_COUNT) { saveData();

// 存储完成清理 list list.clear(); } }

@Override

public void doAfterAllAnalysed(AnalysisContext analysisContext) { // 这⾥也要保存数据,确保最后遗留的数据也存储到数据库 saveData();

logger.info(\"所有数据解析完成!\"); }

private void saveData() {

logger.info(\"{}条数据,开始存储数据库!\ //保存数据

//userService.save(list);

logger.info(\"存储数据库成功!\"); }

}

step3: 读取excel

public class EasyExcelDemo {

public static void main(String[] args) throws Exception {

InputStream fis = new FileInputStream(\"D:\\\\UserInfo.xlsx\"); AnalysisEventListener listener = new UserInfoDataListener();

ExcelReader excelReader = EasyExcel.read(fis, UserInfo.class, listener).build(); ReadSheet readSheet = EasyExcel.readSheet(0).build(); ReadSheet readSheet2 = EasyExcel.readSheet(1).build(); excelReader.read(readSheet);

// 这⾥千万别忘记关闭,读的时候会创建临时⽂件,到时磁盘会崩的 excelReader.finish(); }}

只需要上⾯3步就能进⾏Excel的读取了。⽂件下载Excelpublic class ExcelUtil {

public static OutputStream getOutputStream(String fileName, HttpServletResponse response) throws Exception{ try{

fileName = URLEncoder.encode(fileName,\"utf-8\"); response.setContentType(\"application/vnd.ms-excel\"); response.setCharacterEncoding(\"utf-8\");

//此处指定了⽂件类型为xls,如果是xlsx的,请⾃⾏替换修改

response.setHeader(\"Content-Disposition\ response.setHeader(\"Pragma\

response.setHeader(\"Cache-Control\ response.addHeader(\"Cache-Control\ return response.getOutputStream(); } catch (IOException e){

throw new Exception(\"导出⽂件失败!\"); } }

public static void writeExcel(HttpServletResponse response, List list, String fileName, String sheetName, Class clazz) throws Exception {

ExcelWriter writer = new ExcelWriter(getOutputStream(fileName, response), ExcelTypeEnum.XLS); Sheet sheet = new Sheet(1, 0, clazz); sheet.setSheetName(sheetName); writer.write(list, sheet); writer.finish(); }}

在Controller中我们只要像下⾯这种⽅式调⽤就⾏了。

@RequestMapping(value = \"/file/testExcelDownload\")

public void testExcelDownload(HttpServletRequest request,HttpServletResponse response){ //以下信息从数据库中查出

List excelInfos = new ArrayList<>(); ExcelInfo info1 = new ExcelInfo(); ExcelInfo info2 = new ExcelInfo(); excelInfos.add(info1); excelInfos.add(info2);

info1.setIssuerName(\"name1\"); info1.setRiskLevel(\"level1\"); info2.setIssuerName(\"name1\"); info2.setRiskLevel(\"level1\"); try {

String fileName = \"excelInfo\"; String sheetName = \"sheet1\";

ExcelUtil.writeExcel(response, excelInfos, fileName, sheetName, ExcelInfo.class); } catch(Exception e){

log.error(\"模板下载失败\ } }

在导出Excel的部分,easyExcel还提供了⾃定义样式,插⼊表格,插⼊图⽚等其他功能,还有⼀个⽐较有意思的功能就是Excel模板填充的功能。详细的功能信息参考。⼀些⼩建议

尽量使⽤DTO的模式导出Excel给导出的Excel建⽴单独的DTO模型

exportWithEasyExcel(excelDate,XXDTO.class,\"订单.xlsx\订单\");

private void exportWithEasyExcel(List rows, Class clazz, String fileName,String sheetName) { try {

HttpServletResponse response = WebSessionUtil.getResponse(); HttpServletRequest request = WebSessionUtil.getRequest(); String newFileName = encodeFileName(request, fileName);

response.setContentType(\"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;charset=utf-8\"); response.setHeader(\"Content-Disposition\ ServletOutputStream out = response.getOutputStream();

EasyExcel.write(out,clazz).autoCloseStream(Boolean.FALSE).sheet(StringUtils.isEmpty(sheetName)?\"default\":sheetName) .doWrite(rows); } catch (IOException e) {

throw new CivOprRunTimeException(ResponseType.DOWNLOAD_FILE_FAIL_CODE, e); } }

private String encodeFileName(HttpServletRequest req, String oldFileName) throws UnsupportedEncodingException {

// IE9之前包括IE9都包含MSIE;IE10之后都包含Trident;edge浏览器包含Edge String filename = \"\";

String userAgent = req.getHeader(\"User-Agent\");

if (userAgent.contains(\"MSIE\") || userAgent.contains(\"Trident\") || userAgent.contains(\"Edge\")) { filename = URLEncoder.encode(oldFileName, \"UTF-8\"); } else {

filename = new String(oldFileName.getBytes(\"UTF-8\"), \"ISO8859-1\"); }

return filename; }

使⽤模板模式

easyExcel也⽀持先定义模板,然后准备数据,模板中使⽤占位符的形式取数据。使⽤excel-wrapper对导⼊的数据进⾏注解校验参考

(导⼊Excel,并对字段进⾏校验)官⽹:

因篇幅问题不能全部显示,请点此查看更多更全内容

Copyright © 2019- 69lv.com 版权所有 湘ICP备2023021910号-1

违法及侵权请联系:TEL:199 1889 7713 E-MAIL:2724546146@qq.com

本站由北京市万商天勤律师事务所王兴未律师提供法律服务