EasyExcel简单的使用(课程目录项目文件上传)和实践

1. 课程目录需求

在这里插入图片描述

2.EasyExcel入门

2.1 导入坐标

    <dependencies>
        <!-- easy excel 依赖-->
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>easyexcel</artifactId>
            <version>2.2.6</version>
        </dependency>
        <!--lombok , @Data 等-->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
        </dependency>
        <!--测试起步依赖-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
        </dependency>
    </dependencies>

2.2 封装类

package com.czxy.test.excel;

import com.alibaba.excel.annotation.ExcelProperty;
import lombok.Data;

/**
 * @author 桐叔
 * @email [email protected]
 */
@Data
public class Student {
    
    
    @ExcelProperty("编号")
    private String id;

    @ExcelProperty("姓名")
    private String name;

    @ExcelProperty("年龄")
    private Integer age;

    @ExcelProperty("电话")
    private String telephone;

    @ExcelProperty("邮箱")
    private String email;

    @ExcelProperty("生日")
    private String birthday;
}

2.3 写操作

package com.czxy.test.excel;

import com.alibaba.excel.EasyExcel;
import org.junit.Test;

import java.util.ArrayList;
import java.util.List;

/**
 * @author 桐叔
 * @email [email protected]
 */
public class TestExcelWrite {
    
    

    private List<Student> getData() {
    
    
        List<Student> list = new ArrayList<>();

        for(int i = 0 ; i < 20 ; i ++) {
    
    
            Student student = new Student();
            student.setId( i  + "");
            student.setName("jack" + i);
            student.setAge(i);
            student.setTelephone("13699" + i);
            student.setEmail("jack" + i + "@czxy.com") ;
            student.setBirthday("2021-12-21");

            list.add(student);
        }

        return list;
    }

    @Test
    public void write() {
    
    
        String file = "G:/czxy_2019_java34/xls/student_demo.xls";
        // 进行写操作,确定表头,表名,内容
        EasyExcel.write(file,Student.class).sheet("Java34").doWrite(getData());

    }

}

2.4 读操作

  • 监听器

    package com.czxy.test.excel;
    
    import com.alibaba.excel.context.AnalysisContext;
    import com.alibaba.excel.event.AnalysisEventListener;
    
    /**
     * @author 桐叔
     * @email [email protected]
     */
    public class StudentListener extends AnalysisEventListener<Student> {
          
          
        @Override
        public void invoke(Student student, AnalysisContext analysisContext) {
          
          
            System.out.println(student);
        }
    
        @Override
        public void doAfterAllAnalysed(AnalysisContext analysisContext) {
          
          
            System.out.println("解析完成");
        }
    }
    
    
  • package com.czxy.test.excel;
    
    import com.alibaba.excel.EasyExcel;
    import org.junit.Test;
    
    /**
     * @author 桐叔
     * @email [email protected]
     */
    public class TestExcelRead {
          
          
    
        private String getPath() {
          
          
            return TestExcelRead.class.getResource("/").getPath();
        }
    
        @Test
        public void testRead() {
          
          
            // 确定文件位置 : E:\workspaces_2019\zx-parent-1228\zx-test-parent\zx-test-excel\target\classes\student_demo.xls
            String file = getPath() + "student_demo.xls";
            // 读取excel文件
            EasyExcel.read(file,Student.class, new StudentListener()).sheet("Java78").doRead();
    
        }
    }
    
    

3.课程目录批量导入

3.1 前端实现

在这里插入图片描述

  • 添加upload组件

在这里插入图片描述

    <!-- 文件上传 -->
    <el-upload
      class="upload-demo"
      action="http://localhost:10010/v2/course-service/subject/upload"
      multiple
      :limit="1"
      :on-exceed="handleExceed"
      :before-upload="beforeAvatarUpload"
      :file-list="fileList">
      <el-button size="small" type="primary">点击上传</el-button>
      <div slot="tip" class="el-upload__tip">只能上传xls/xlsx文件,且不超过2MB</div>
    </el-upload>
  • 声明变量

      data() {
          
          
        return {
          
          
          fileList: [],         //上传文件列表
        }
      },
    
  • 定义函数

    methods() {
          
          
        handleExceed(files, fileList) {
          
          
          this.$message.warning(`当前限制选择 1 个文件,本次选择了 ${
            
            files.length} 个文件,共选择了 ${
            
            files.length + fileList.length} 个文件`);
        },
        beforeAvatarUpload(file) {
          
          
          const isXls = file.type === 'application/vnd.ms-excel';
          const isXlsx = file.type === 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet';
          if (!isXls && !isXlsx) {
          
          
            this.$message.error('上传文件只能是 xls/xlsx 格式!');
          }
    
          const isLt2M = file.size / 1024 / 1024 < 2;
          if (!isLt2M) {
          
          
            this.$message.error('上传头像图片大小不能超过 2MB!');
          }
          return (isXls || isXlsx)  && isLt2M;
        }
    }
    
  • 成功回调

在这里插入图片描述

3.2 后端实现:controller页面

  • element-ui upload组件,上传默认字段名为file,后端从头roller中,需要提供一个类型为MultipartFile变量file

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-CPX0TxFH-1617869070858)(assets/image-20210311115136873.png)]

    @PostMapping("/upload")
    public BaseResult upload(MultipartFile file) throws IOException {
    
    
        System.out.println(file.getInputStream());
        return BaseResult.ok("上传成功");
    }

4.1 批量导入

4.1.0 前提

  • 需要在zuul中放行上传请求

在这里插入图片描述

4.1.1 后端excel解析

  • 编写SubjectVo,用于封装excel一行数据

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-NvyI0O2T-1617869274191)(assets/image-20210312083905919.png)]

    package com.czxy.zx.course;
    
    import com.alibaba.excel.annotation.ExcelProperty;
    import lombok.Data;
    
    /**
     * @author 桐叔
     * @email [email protected]
     */
    @Data
    public class SubjectVo {
          
          
        @ExcelProperty("一级分类")
        private String firstSubject;
    
        @ExcelProperty("二级分类")
        private String secondSubject;
    }
    
    
  • 编写controller,用于解析excel

        @PostMapping("/upload")
        public BaseResult upload(MultipartFile file) throws IOException {
          
          
            // 上传文件原始名
            // System.out.println(file.getOriginalFilename());
            // 获得上传文件内容
            // System.out.println(file.getInputStream());
    
            // 解析xls文件  read(流,封装对象,处理类).sheet(表名/表索引).doRead()
            EasyExcel.read(file.getInputStream(), SubjectVo.class, subjectListener).sheet(0).doRead();
    
            return BaseResult.ok("上传成功");
        }
    
  • 编写excel解析处理类 SubjectListener

    • 使用@Component交于spring管理处理类
    package com.czxy.zx.course.listener;
    
    import com.alibaba.excel.context.AnalysisContext;
    import com.alibaba.excel.event.AnalysisEventListener;
    import com.czxy.zx.course.SubjectVo;
    import org.springframework.stereotype.Component;
    
    /**
     * @author 桐叔
     * @email [email protected]
     */
    @Component
    public class SubjectListener extends AnalysisEventListener<SubjectVo> {
          
          
        @Override
        public void invoke(SubjectVo studentVo, AnalysisContext context) {
          
          
            System.out.println(studentVo);
        }
    
        @Override
        public void doAfterAllAnalysed(AnalysisContext context) {
          
          
    
        }
    }
    
    

1.1.2 后端处理解析内容

  • 需求:

    • 一级科目:
      • 通过科目名称获得一级科目,parent_id=0表示一级科目(一级名称不能重复)
      • 如果不存在,添加一个新的一级科目
    • 二级科目:
      • 通过二级科目名称从一级科目下查询(在一级科目下,二级科目不能重复)
      • 如果不存在,给一级科目添加一个新的二级科目 parent_id=一级科目id
  • 修改EduSubject

    package com.czxy.zx.domain;
    
    import com.baomidou.mybatisplus.annotation.*;
    import com.fasterxml.jackson.annotation.JsonFormat;
    import lombok.Data;
    
    import java.util.ArrayList;
    import java.util.Date;
    import java.util.List;
    
    /**
     * @author 桐叔
     * @email [email protected]
     */
    @TableName("edu_subject")
    @Data
    public class EduSubject {
          
          
        @TableId(type = IdType.ASSIGN_UUID)
        //课程科目ID
        private String id;
        //科目名称
        private String title;
        //父ID
        private String parentId;
        //排序字段
        private Integer sort;
        //创建时间
        @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss",timezone = "GMT+8")
        @TableField(fill = FieldFill.INSERT)
        private Date gmtCreate;
        //更新时间
        @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss",timezone = "GMT+8")
        @TableField(fill = FieldFill.INSERT_UPDATE)
        private Date gmtModified;
    
        @TableField(exist = false)
        private List<EduSubject> children = new ArrayList<>();
    }
    
    
  • 完成填充处理类

在这里插入图片描述

package com.czxy.zx.course.handler;

import com.baomidou.mybatisplus.core.handlers.MetaObjectHandler;
import org.apache.ibatis.reflection.MetaObject;
import org.springframework.stereotype.Component;

import java.util.Date;

/**
 * @author 桐叔
 * @email [email protected]
 */
@Component
public class DateMetaObjectHandler implements MetaObjectHandler {
    
    
    @Override
    public void insertFill(MetaObject metaObject) {
    
    
        // 添加
        this.setFieldValByName("gmtCreate", new Date(), metaObject);
        this.setFieldValByName("gmtModified", new Date(), metaObject);
    }

    @Override
    public void updateFill(MetaObject metaObject) {
    
    
        // 修改
        this.setFieldValByName("gmtModified", new Date(), metaObject);

    }
}

  • 编写上传监听处理类:一级科目

    package com.czxy.zx.course.listener;
    
    import com.alibaba.excel.context.AnalysisContext;
    import com.alibaba.excel.event.AnalysisEventListener;
    import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
    import com.czxy.zx.course.SubjectVo;
    import com.czxy.zx.course.mapper.EduSubjectMapper;
    import com.czxy.zx.course.service.EduSubjectService;
    import com.czxy.zx.domain.EduSubject;
    import org.springframework.stereotype.Component;
    
    import javax.annotation.Resource;
    
    /**
     * @author 桐叔
     * @email [email protected]
     */
    @Component
    public class SubjectListener extends AnalysisEventListener<SubjectVo> {
          
          
    
        @Resource
        private EduSubjectService eduSubjectService;
    
        @Override
        public void invoke(SubjectVo studentVo, AnalysisContext context) {
          
          
            System.out.println(studentVo);
    
            // 1.一级科目
            // 1.1 查询一级科目:父=0 , 名称
            QueryWrapper firstQueryWrapper = new QueryWrapper();
            firstQueryWrapper.eq("parent_id", "0");
            firstQueryWrapper.eq("title",studentVo.getFirstSubject());
            EduSubject firstSubject = eduSubjectService.getOne(firstQueryWrapper);
            // 1.2 不存在,新加
            if(firstSubject == null ) {
          
          
                firstSubject = new EduSubject();
                // id 随机生成uuid
                firstSubject.setTitle(studentVo.getFirstSubject());
                firstSubject.setParentId("0");
                firstSubject.setSort(0);
                // 创建时间、修改时间 -- MyBatisPlus数据填充
                eduSubjectService.save(firstSubject);
            }
    
    
            // 二级科目
    
    
    
    
    
    
    
    
        }
    
        @Override
        public void doAfterAllAnalysed(AnalysisContext context) {
          
          
    
        }
    }
    
    
  • 编写上传监听处理类:二级科目

    package com.czxy.zx.course.listener;
    
    import com.alibaba.excel.context.AnalysisContext;
    import com.alibaba.excel.event.AnalysisEventListener;
    import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
    import com.czxy.zx.course.SubjectVo;
    import com.czxy.zx.course.mapper.EduSubjectMapper;
    import com.czxy.zx.course.service.EduSubjectService;
    import com.czxy.zx.domain.EduSubject;
    import org.springframework.stereotype.Component;
    
    import javax.annotation.Resource;
    
    /**
     * @author 桐叔
     * @email [email protected]
     */
    @Component
    public class SubjectListener extends AnalysisEventListener<SubjectVo> {
          
          
    
        @Resource
        private EduSubjectService eduSubjectService;
    
        @Override
        public void invoke(SubjectVo studentVo, AnalysisContext context) {
          
          
            System.out.println(studentVo);
    
            // 1.一级科目
            // 1.1 查询一级科目:父=0 , 名称
            QueryWrapper firstQueryWrapper = new QueryWrapper();
            firstQueryWrapper.eq("parent_id", "0");
            firstQueryWrapper.eq("title",studentVo.getFirstSubject());
            EduSubject firstSubject = eduSubjectService.getOne(firstQueryWrapper);
            // 1.2 不存在,新加
            if(firstSubject == null ) {
          
          
                firstSubject = new EduSubject();
                // id 随机生成uuid
                firstSubject.setTitle(studentVo.getFirstSubject());
                firstSubject.setParentId("0");
                firstSubject.setSort(0);
                // 创建时间、修改时间 -- MyBatisPlus数据填充
                eduSubjectService.save(firstSubject);
            }
    
    
            // 2 二级科目
            // 2.1 查询二级科目
            QueryWrapper secondQueryWrapper = new QueryWrapper();
            secondQueryWrapper.eq("parent_id", firstSubject.getId());
            secondQueryWrapper.eq("title",studentVo.getSecondSubject());
            EduSubject secondSubject = eduSubjectService.getOne(secondQueryWrapper);
    
            // 2.2 不存在,添加
            if(secondSubject == null) {
          
          
                secondSubject = new EduSubject();
                // id 随机生成uuid
                // 1)二级科目的名称
                secondSubject.setTitle(studentVo.getSecondSubject());
                // 2) 二级科目所属一级科目的id
                secondSubject.setParentId(firstSubject.getId());
                secondSubject.setSort(0);
                // 创建时间、修改时间 -- MyBatisPlus数据填充
                eduSubjectService.save(secondSubject);
            }
    
    
        }
    
        @Override
        public void doAfterAllAnalysed(AnalysisContext context) {
          
          
    
        }
    }
    
    

猜你喜欢

转载自blog.csdn.net/li13429743580/article/details/115523134