EasyExcel
EasyExcel是阿里巴巴开源poi插件之一,主要解决了poi框架使用复杂,sax解析模式不容易操作,数据量大起来容易OOM,解决了POI并发造成的报错。
主要解决方式:通过解压文件的方式加载,一行一行的加载,并且抛弃样式字体等不重要的数据,降低内存的占用。
EasyExcel优势
- 注解式自定义操作
- 输入输出简单,提供输入输出过程的接口
- 支持一定程度的单元格合并等灵活化操作
常用注解
- @ExcelProperty指定当前字段对应excel中的那一列。可以根据名字或者Index去匹配。当然也可以不写,默认第一个字段就是index=0,以此类推。千万注意,要么全部不写,要么全部用index,要么全部用名字去匹配。千万别三个混着用,除非你非常了解源代码中三个混着用怎么去排序的。
- @ExcelIgnore默认所有字段都会和excel去匹配,加了这个注解会忽略该字段
- @DateTimeFormat日期转换,用String去接收excel日期格式的数据会调用这个注解。里面的value参照java.text.SimpleDateFormat
- @NumberFormat数字转换,用String去接收excel数字格式的数据会调用这个注解。里面的value参照java.text.DecimalFormat
- @ExcelIgnoreUnannotated过滤属性没有@ExcelProperty注解的字段
依赖
<dependency><groupId>com.alibaba</groupId><artifactId>easyexcel</artifactId><version>3.1.0</version><exclusions><exclusion><artifactId>poi-ooxml-schemas</artifactId><groupId>org.apache.poi</groupId></exclusion></exclusions></dependency>
写
写完后通过web直接下载
controller层
@ResponseBody@GetMapping("/studentDownload")publicStringdownload(HttpServletResponse response){
studentService.writeToExcel(response);return"download success";}
service层
@OverridepublicvoidwriteToExcel(HttpServletResponse response){// 使用swagger 会导致各种问题,请直接用浏览器或者用postman
response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
response.setCharacterEncoding("utf-8");// 这里URLEncoder.encode可以防止中文乱码 当然和easyexcel没有关系String fileName =null;try{
fileName =URLEncoder.encode("学生表"+System.currentTimeMillis(),"UTF-8").replaceAll("\\+","%20");}catch(UnsupportedEncodingException e){
e.printStackTrace();}
response.setHeader("Content-disposition","attachment;filename*=utf-8''"+ fileName +".xlsx");try{ExcelWriter excelWriter =EasyExcel.write(response.getOutputStream(),Student.class).build();WriteSheet writeSheet =EasyExcel.writerSheet("one").build();int total = studentMapper.selectTotal();int pages = total % NUMBER_OF_WRITES_PER_TIME ==0? total / NUMBER_OF_WRITES_PER_TIME
: total / NUMBER_OF_WRITES_PER_TIME +1;System.out.println(pages);for(int i =1; i <= pages; i++){// 分页去数据库查询数据 这里可以去数据库查询每一页的数据List<Student> data =dataList(i);
data.forEach(System.out::println);
excelWriter.write(data, writeSheet);}
excelWriter.finish();}catch(IOException e){
e.printStackTrace();}}
访问
结果
读
通过web上传
@PostMapping("/studentUpload")@ResponseBodypublicStringupload(MultipartFile file)throwsIOException{System.out.println("------upload--------------");InputStream inputStream = file.getInputStream();// 有个很重要的点 DemoDataListener 不能被spring管理,要每次读取excel都要new,然后里面用到spring可以构造方法传进去// 这里 需要指定读用哪个class去读,然后读取第一个sheet 文件流会自动关闭EasyExcel.read(inputStream,Student.class,newStudentListener(studentService)).sheet().doRead();return"upload success";}
解析到每一条数据都会调用一次listener进行处理,需要的业务逻辑操作都写在listener内部即可
listener写法
此listener逻辑
- 每100条数据进行一次存储数据库操作
- 每条数据拿到后进行校验,校验不合法不放入list
/**
* @author QN
*/@Slf4jpublicclassStudentListenerimplementsReadListener<Student>{/**
* 每隔100条存储数据库,然后清理list ,方便内存回收
*/privatestaticfinalint BATCH_COUNT =100;/**
* 缓存的数据
*/privateList<Student> cachedDataList =ListUtils.newArrayListWithExpectedSize(BATCH_COUNT);privateStudentService studentService;/**
* 如果使用了spring,请使用这个构造方法。每次创建Listener的时候需要把spring管理的类传进来
*
*/publicStudentListener(StudentService studentService){this.studentService = studentService;}/**
* 这个每一条数据解析都会来调用
*
* @param data one row value. Is is same as {@link AnalysisContext#readRowHolder()}
* @param context
*/@Overridepublicvoidinvoke(Student data,AnalysisContext context){Gson gson =newGson();
log.info("解析到一条数据:{}",gson.toJson(data));boolean b = studentService.registerCheck(data.getStu_no(), data.getStu_password());if(b){
data.setStu_password(studentService.Digest(data.getStu_password()));
cachedDataList.add(data);// 达到BATCH_COUNT了,需要去存储一次数据库,防止数据几万条数据在内存,容易OOMif(cachedDataList.size()>= BATCH_COUNT){saveData();// 存储完成清理 list
cachedDataList =ListUtils.newArrayListWithExpectedSize(BATCH_COUNT);}}}/**
* 所有数据解析完成了 都会来调用
*
* @param context
*/@OverridepublicvoiddoAfterAllAnalysed(AnalysisContext context){// 这里也要保存数据,确保最后遗留的数据也存储到数据库saveData();
log.info("所有数据解析完成!");}/**
* 加上存储数据库
*/privatevoidsaveData(){
log.info("{}条数据,开始存储数据库!", cachedDataList.size());
studentService.saveBatch(cachedDataList);
log.info("存储数据库成功!");}}
结尾
更多详细操作,阅读EasyExcel官方文档
版权归原作者 QiNian_G 所有, 如有侵权,请联系我们删除。