0


EasyExcel使用

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官方文档


本文转载自: https://blog.csdn.net/qq_42878320/article/details/124914760
版权归原作者 QiNian_G 所有, 如有侵权,请联系我们删除。

“EasyExcel使用”的评论:

还没有评论