谷粒学院(九)EasyExcel | 课程分类模块(上)

简介: 谷粒学院(九)EasyExcel | 课程分类模块

一、EasyExcel 简介

1、Excel导入导出的应用场景

  • 数据导入:减轻录入工作量
  • 数据导出:统计信息归档
  • 数据传输:异构系统之间数据传输

2、EasyExcel特点

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


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


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

3、案例1:EasyExcel进行Excel写操作

1、pom中引入xml相关依赖

<dependencies>
    <!-- https://mvnrepository.com/artifact/com.alibaba/easyexcel -->
    <dependency>
        <groupId>com.alibaba</groupId>
        <artifactId>easyexcel</artifactId>
        <version>2.1.1</version>
    </dependency>
    <!-- 因为EasyExcel底层是Poi所以需要引入poi的依赖 -->
    <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>
</dependencies>

2、创建实体类

@Data
public class WriteData {
    //设置excel表头名称
    @ExcelProperty("学生编号")
    private Integer sno;
    @ExcelProperty("学生姓名")
    private String sname;
}

3、实现写操作

public static void testWrite(){
    //实现excel的写操作
    //1.设置写入文件夹地址和excel名称
    String filename = "F:\\write.xlsx";
    //2.调用easyexcel里面的方法实现写操作
    EasyExcel.write(filename, WriteData.class).sheet("学生列表").doWrite(getData());
}
public static List <WriteData> getData(){
    List <WriteData> list = new ArrayList <>();
    for(int i = 0;i < 10;i++){
        String sname = "lucy"+i;
        list.add(new WriteData(i, sname));
    }
    return list;
}

4、案例2:EasyExcel进行Excel读操作

1、创建实体类并标记对应列关系

@Data
public class ReadData {
    //设置excel表头名称
    @ExcelProperty(index = 0)
    private Integer sno;
    @ExcelProperty(index = 1)
    private String sname;
}

2、创建监听器进行excel文件读取

public class ExcelListner extends AnalysisEventListener<ReadData> {
   List<ReadData> list =  new ArrayList<ReadData>();
   //一行一行的去读取
    @Override
    public void invoke(ReadData readData, AnalysisContext analysisContext) {
        System.out.println("****"+readData);
        list.add(readData);
    }
    //读取Excel表头信息
    @Override
    public void invokeHeadMap(Map <Integer, String> headMap, AnalysisContext context) {
        System.out.println("表头信息:"+headMap);
    }
    //读取完成之后执行
    @Override
    public void doAfterAllAnalysed(AnalysisContext analysisContext) {
    }
}

3、进行读操作

public static void testRead(){
    String filename = "F:\\write.xlsx";
    EasyExcel.read(filename,ReadData.class,new ExcelListner()).sheet().doRead();
}

二、课程分类添加功能(后端)

核心:EasyExcel读取excel内容实现

1、引入easyexcel依赖

2、使用代码生成器把课程分类代码生成

5b8f58f473fdc9e49b6602f28bdb562b.png


3、创建实体类和excel对应关系

@Data
public class SubjectData {
    @ExcelProperty(index = 0)
    private String oneSujectName;
    @ExcelProperty(index = 1)
    private String twoSujectName;
}


4、编写 EduSubjectController 类

@Api(description = "课程分类")
@RestController
@RequestMapping("/eduservice/subject")
@CrossOrigin
public class EduSubjectController {
    @Autowired
    private EduSubjectService eduSubjectService;
    //添加课程分类
    @ApiOperation(value = "添加课程分类")
    @PostMapping("addSubjects")
    public R addSubjects(MultipartFile file){
        boolean flag = eduSubjectService.saveSubjects(file);
        if(flag){
            return R.ok().message("文件导入成功!");
        }else{
            return R.error().message("文件导入失败!");
        }
    }
}

5、编写EduSubjectServiceImpl 类

@Service
public class EduSubjectServiceImpl extends ServiceImpl<EduSubjectMapper, EduSubject> implements EduSubjectService {
    @Autowired
    private EduSubjectService eduSubjectService;
    //添加课程分类
    @Override
    public boolean saveSubjects(MultipartFile file) {
        try {
            InputStream inputStream = file.getInputStream();
            //进行excel文件读取
            EasyExcel.read(inputStream, SubjectData.class, new SubjectExcelListner(eduSubjectService)).sheet().doRead();
            return true;
        }catch (Exception e){
            e.printStackTrace();
            return false;
        }
    }
}

6、创建读取Excel监听器

public class SubjectExcelListner extends AnalysisEventListener<SubjectData> {
    //因为SubjectExcelListner在EduSubjectServiceImpl每次会被new的形式使用,所以SubjectExcelListner不能交给
    //Spring进行管理,也就不能使用@Autowird或@Resource注解注入对象.
    //但是该类需要调用service中的方法进行数据库操作,该如何使用呢?
    //可以通过构造方法传递参数的形式,使用service对象.
    private EduSubjectService eduSubjectService;
    public SubjectExcelListner(EduSubjectService eduSubjectService) {
        this.eduSubjectService = eduSubjectService;
    }
    public SubjectExcelListner() {}
    //一行一行的去读取
    @Override
    public void invoke(SubjectData subjectData, AnalysisContext analysisContext) {
        if(subjectData==null){
            throw new GuLiException(20001,"数据为空!");
        }
        //添加一级分类
        EduSubject oneSubject = this.existOneSubject(subjectData.getOneSubjectName());
        if(oneSubject==null){//没有相同的一级分类
            oneSubject = new EduSubject();
            oneSubject.setTitle(subjectData.getOneSubjectName());
            oneSubject.setParentId("0");
            eduSubjectService.save(oneSubject);
        }
        //获取一级分类id
        String pid = oneSubject.getId();
        //添加二级分类
        EduSubject twoSubject = this.existTwoSubject(subjectData.getTwoSubjectName(), pid);
        if(twoSubject==null){
            twoSubject = new EduSubject();
            twoSubject.setTitle(subjectData.getTwoSubjectName());
            twoSubject.setParentId(pid);
            eduSubjectService.save(twoSubject);
        }
    }
    //读取Excel表头
    @Override
    public void invokeHeadMap(Map <Integer, String> headMap, AnalysisContext context) {
        System.out.println("表头信息:"+headMap);
    }
    //读取完成后的操作
    @Override
    public void doAfterAllAnalysed(AnalysisContext analysisContext) {
    }
    //判断一级分类是否重复
    private EduSubject existOneSubject(String name){
        QueryWrapper <EduSubject> wrapper = new QueryWrapper <>();
        wrapper.eq("title", name).eq("parent_id",0);
        EduSubject subject = eduSubjectService.getOne(wrapper);
        return subject;
    }
    //判断二级分类是否重复
    private EduSubject existTwoSubject(String name,String pid){
        QueryWrapper <EduSubject> wrapper = new QueryWrapper <>();
        wrapper.eq("title", name).eq("parent_id", pid);
        EduSubject subject = eduSubjectService.getOne(wrapper);
        return subject;
    }
}
相关文章
DataGrip之一个赏心悦目的SQL格式化模板,快用起来吧
DataGrip之一个赏心悦目的SQL格式化模板,快用起来吧
DataGrip之一个赏心悦目的SQL格式化模板,快用起来吧
|
消息中间件 SQL 存储
超详细的RabbitMQ入门,看这篇就够了!
RabbitMQ入门,看这篇就够了
224325 69
|
12月前
|
移动开发 开发工具 Android开发
Uniapp与原生App集成的流程
Uniapp与原生App集成的流程
4137 156
|
安全 JavaScript Java
java Web 项目完整案例实操指南包含从搭建到部署的详细步骤及热门长尾关键词解析的实操指南
本项目为一个完整的JavaWeb应用案例,采用Spring Boot 3、Vue 3、MySQL、Redis等最新技术栈,涵盖前后端分离架构设计、RESTful API开发、JWT安全认证、Docker容器化部署等内容,适合掌握企业级Web项目全流程开发与部署。
1204 0
|
JSON 前端开发 API
以项目登录接口为例-大前端之开发postman请求接口带token的请求测试-前端开发必学之一-如果要学会联调接口而不是纯写静态前端页面-这个是必学-本文以优雅草蜻蜓Q系统API为实践来演示我们如何带token请求接口-优雅草卓伊凡
以项目登录接口为例-大前端之开发postman请求接口带token的请求测试-前端开发必学之一-如果要学会联调接口而不是纯写静态前端页面-这个是必学-本文以优雅草蜻蜓Q系统API为实践来演示我们如何带token请求接口-优雅草卓伊凡
1163 5
以项目登录接口为例-大前端之开发postman请求接口带token的请求测试-前端开发必学之一-如果要学会联调接口而不是纯写静态前端页面-这个是必学-本文以优雅草蜻蜓Q系统API为实践来演示我们如何带token请求接口-优雅草卓伊凡
|
JavaScript 应用服务中间件 nginx
Vue项目部署:如何打包并上传至服务器进行部署?
以上就是Vue项目打包及部署的方法,希望对你有所帮助。描述中可能会有一些小疏漏,但基本流程应该没有问题。记住要根据你的实际情况调整对应的目录路径和服务器IP地址等信息。此外,实际操作时可能会遇到各种问题,解决问题的能力是每一位开发者必备的技能。祝你部署顺利!
2961 17
|
PHP 开发者
深入理解PHP中的面向对象编程
【10月更文挑战第2天】 本文将详细探讨PHP中的面向对象编程(OOP)概念,从基础语法到高级应用,带领读者一步步深入理解PHP的OOP。无论是PHP初学者还是有一定经验的开发者,都能在本文中找到有价值的内容。通过实际案例和代码示例,我们将揭示OOP的核心理念及其在PHP中的应用,帮助您提升编程技能,写出更高效、更易维护的代码。
229 3
|
自然语言处理 IDE 开发工具
通义灵码使用安装教程,3 分钟快速上手体验
通义灵码,是阿里云与通义实验室联合出品的一款基于通义大模型的智能编码辅助工具,提供行级/函数级实时续写、自然语言生成代码、单元测试生成、代码优化、注释生成、代码解释、研发智能问答、异常报错排查等能力,并针对阿里云的云服务使用场景调优,助力开发者高效、流畅的编码。目前个人版免费使用。
6474 10
|
前端开发 Java C++
超简单使用Vite+Vue3构建共享开发和分模块打包的前端项目
使用Vite和Vue3构建支持共享组件和分模块独立打包的前端项目的方法。
2021 0
超简单使用Vite+Vue3构建共享开发和分模块打包的前端项目
apache.commons.lang3常用工具类
apache.commons.lang3常用工具类
555 2