• EasyExcel的用法


    一.Excel导入导出的应用场景

    1.数据导入:减轻录入的工作量

    2.数据导出:统计信息归档

    3.数据传输:异构系统之间数据传输

    二。EasyExcel简介

    1.EasyExcel特点

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

    EasyExcel是阿里巴巴开源的一个excel处理框架,以使用简单,节省内存著称,EasyExcel能大大减少占用内存的主要原因是在解析Excel时没有将文件数据一次性全部加载到内存中,而是从磁盘上一行行读取数据,逐个解析。

    EasyExcel采用一行一行的解析模式,并将一行的解析结果以观察者的模式通知处理(AnalysisEventListener)。

    1.导入maven依赖,主要还需要poi的依赖,并且版本要对应上

    <!-- https://mvnrepository.com/artifact/com.alibaba/easyexcel -->
    <dependency>
      <groupId>com.alibaba</groupId>
      <artifactId>easyexcel</artifactId>
      <version>2.1.1</version>
    </dependency>

    <!--xls-->
    <dependency>
      <groupId>org.apache.poi</groupId>
      <artifactId>poi</artifactId>
      <version>3.17</version>
    </dependency>
    <dependency>
      <groupId>org.apache.poi</groupId>
      <artifactId>poi-ooxml</artifactId>
      <version>3.17</version>
    </dependency>

    2.编写entity对象类

    @Data
    public class DemoData {
        //设置excel表头名称
        @ExcelProperty(value = "学生编号",index = 0)
        private Integer sno;
        @ExcelProperty(value = "学生姓名",index = 1)
        private String sname;
    }

    3.写操作

    public class TestEasyExcelWrite {
    
        public static void main(String[] args) {
    
            //实现excel写的操作
            //1 设置写入文件夹地址和excel文件名称
            String filename = "C:\Users\aus\write.xlsx";
           // 2 调用easyexcel里面的方法实现写操作
           // write方法两个参数:第一个参数文件路径名称,第二个参数实体类class
            EasyExcel.write(filename,DemoData.class).sheet("学生列表").doWrite(getData());
    
        }
    
        //创建方法返回list集合
        private static List<DemoData> getData() {
            List<DemoData> list = new ArrayList<>();
            for (int i = 0; i < 10; i++) {
                DemoData data = new DemoData();
                data.setSno(i);
                data.setSname("lucy"+i);
                list.add(data);
            }
            return list;
        }
    }

    4.最终效果 

     5.读取excel需要先写一个监听器继承AnalysisEventListener

    public class ExcelListener extends AnalysisEventListener<DemoData> {
        //一行一行读取excel内容
        @Override
        public void invoke(DemoData data, AnalysisContext analysisContext) {
            System.out.println("****"+data);
        }
        //读取表头内容
        @Override
        public void invokeHeadMap(Map<Integer, String> headMap, AnalysisContext context) {
            System.out.println("表头:"+headMap);
        }
        //读取完成之后
        @Override
        public void doAfterAllAnalysed(AnalysisContext analysisContext) { }
    }

    6.读取excel代码

    public class TestEasyExcelRead {
    
        public static void main(String[] args) {
    
            //实现excel读操作
            String filename = "C:\Users\aus\write.xlsx";
            EasyExcel.read(filename,DemoData.class,new ExcelListener()).sheet().doRead();
        }
    }

    打印效果见下图:


    实际项目中开发

    entity

    @Data
    @EqualsAndHashCode(callSuper = false)
    @Accessors(chain = true)
    @ApiModel(value="EduSubject对象", description="课程科目")
    public class EduSubject implements Serializable {
    
        private static final long serialVersionUID = 1L;
    
        @ApiModelProperty(value = "课程类别ID")
        @TableId(value = "id", type = IdType.ID_WORKER_STR)
        private String id;
    
        @ApiModelProperty(value = "类别名称")
        private String title;
    
        @ApiModelProperty(value = "父ID")
        private String parentId;
    
        @ApiModelProperty(value = "排序字段")
        private Integer sort;
    
        @ApiModelProperty(value = "创建时间")
        @TableField(fill = FieldFill.INSERT)
        private Date gmtCreate;
    
        @ApiModelProperty(value = "更新时间")
        @TableField(fill = FieldFill.INSERT)
        private Date gmtModified;
        
    }
    @Data
    public class SubjectData {
        @ExcelProperty(index = 0)
        private String oneSubjectName;
        @ExcelProperty(index = 1)
        private String twoSubjectName;
    }

    Controller层

    @RestController
    @RequestMapping("/eduservice/subject")
    @CrossOrigin
    public class EduSubjectController {
    
    
        @Autowired
        private EduSubjectService subjectService;
    
        //添加课程分类
        //获取上传过来文件,把文件内容读取出来
        @PostMapping("addSubject")
        public R addSubject(MultipartFile file) {
            //上传过来excel文件
            subjectService.saveSubject(file,subjectService);
            return R.ok();
        }
    
    }

    service层

    @Service
    public class EduSubjectServiceImpl extends ServiceImpl<EduSubjectMapper, EduSubject> implements EduSubjectService {
    
        @Override
        public void saveSubject(MultipartFile file, EduSubjectService subjectService) {
    
            try{
                InputStream in = file.getInputStream();
                EasyExcel.read(in, SubjectData.class,new SubjectExcelListener(subjectService)).sheet().doRead();
            } catch (Exception e) {
                e.printStackTrace();
            }
    
        }
    }

     5.监听器继承AnalysisEventListener,这里需要注意的点,因为业务层的SubjectExcelListener 并没有交给Spring容器来管理,所以监听器代码无法注入EduSubjectService ,

    这里通过构造方法的方式传过来,从而完成对数据库的操作。

    public class SubjectExcelListener extends AnalysisEventListener<SubjectData> {
    
        //因为SubjectExcelListener不交给spring进行管理,需要自己new,不能注入其他对象
        //不能实现数据库操作
        public EduSubjectService subjectService;
        public SubjectExcelListener() {}
        public SubjectExcelListener(EduSubjectService subjectService) {
            this.subjectService = subjectService;
        }
    
        //读取excel内容,一行一行进行读取
        @Override
        public void invoke(SubjectData subjectData, AnalysisContext analysisContext) {
            if(subjectData == null) {
                throw new GuliException(20001,"文件数据为空");
            }
    
            //一行一行读取,每次读取有两个值,第一个值一级分类,第二个值二级分类
            //判断一级分类是否重复
            EduSubject existOneSubject = this.existOneSubject(subjectService, subjectData.getOneSubjectName());
            if(existOneSubject == null) { //没有相同一级分类,进行添加
                existOneSubject = new EduSubject();
                existOneSubject.setParentId("0");
                existOneSubject.setTitle(subjectData.getOneSubjectName());//一级分类名称
                subjectService.save(existOneSubject);
            }
    
            //获取一级分类id值
            String pid = existOneSubject.getId();
    
            //添加二级分类
            //判断二级分类是否重复
            EduSubject existTwoSubject = this.existTwoSubject(subjectService, subjectData.getTwoSubjectName(), pid);
            if(existTwoSubject == null) {
                existTwoSubject = new EduSubject();
                existTwoSubject.setParentId(pid);
                existTwoSubject.setTitle(subjectData.getTwoSubjectName());//二级分类名称
                subjectService.save(existTwoSubject);
            }
        }
    
        //判断一级分类不能重复添加
        private EduSubject existOneSubject(EduSubjectService subjectService,String name) {
            QueryWrapper<EduSubject> wrapper = new QueryWrapper<>();
            wrapper.eq("title",name);
            wrapper.eq("parent_id","0");
            EduSubject oneSubject = subjectService.getOne(wrapper);
            return oneSubject;
        }
    
        //判断二级分类不能重复添加
        private EduSubject existTwoSubject(EduSubjectService subjectService,String name,String pid) {
            QueryWrapper<EduSubject> wrapper = new QueryWrapper<>();
            wrapper.eq("title",name);
            wrapper.eq("parent_id",pid);
            EduSubject twoSubject = subjectService.getOne(wrapper);
            return twoSubject;
        }
    
        @Override
        public void doAfterAllAnalysed(AnalysisContext analysisContext) {
    
        }
    }
  • 相关阅读:
    圣杯布局总结
    新手用pyCharm编辑器创建项目不知道如何选择(适用于遇到同样问题的新手)
    支付宝小程序日期选择组件datePicker封装
    关于 WebView 的一些笔记
    ES6学习之箭头函数
    MongoDB--在windows下的安装过程及基本配置
    使用HTML5的canvas做图片剪裁
    git常见操作和常见错误
    算法——找出缺失的整数
    入坑涨姿势
  • 原文地址:https://www.cnblogs.com/liuyi13535496566/p/12634898.html
Copyright © 2020-2023  润新知