• EasyExcel综合课程实战


    目录

    预热测试

    实现写操作,对Excel

    对Excel读数据 

    项目结合

    二级分类

    控制层上传Excel文件读取课程

    业务层读取Excel

    Excel的监听器


    场景

    当我们导入课程信息,直接导入Excel文件即可录入所有课程信息,它是行模式读取文件信息,节省内存,效率较高;

    预热测试

    1. <dependencies>
    2. <dependency>
    3. <groupId>com.alibabagroupId>
    4. <artifactId>easyexcelartifactId>
    5. <version>2.1.1version>
    6. dependency>
    7. dependencies>

    2.创建实体类

    一个是一级

    1. package com.atguigu.demo.excel;
    2. import com.alibaba.excel.annotation.ExcelProperty;
    3. import lombok.Data;
    4. @Data
    5. public class DemoData {
    6. //设置表头名称
    7. @ExcelProperty(value = "学生编号",index = 0)
    8. private Integer sno;
    9. @ExcelProperty(value = "学生姓名",index = 1)
    10. private String sname;
    11. }

    实现写操作,对Excel

    指定文件名,在文件中write(),并且封装data数据

    1. public static void main(String[] args) throws Exception {
    2. // 写法1
    3. String fileName = "F:\\11.xlsx";
    4. // 这里 需要指定写用哪个class去写,然后写到第一个sheet,名字为模板 然后文件流会自动关闭
    5. // 如果这里想使用03 则 传入excelType参数即可
    6. EasyExcel.write(fileName, DemoData.class).sheet("写入方法一").doWrite(data());
    7. }
    8. //循环设置要添加的数据,最终封装到list集合中
    9. private static List data() {
    10. List list = new ArrayList();
    11. for (int i = 0; i < 10; i++) {
    12. DemoData data = new DemoData();
    13. data.setSno(i);
    14. data.setSname("张三"+i);
    15. list.add(data);
    16. }
    17. return list;
    18. }

    对Excel读数据 

    主要是通过ExcelListener监听器从Excel中获取行数据

    1. package com.atguigu.demo.excel;
    2. import com.alibaba.excel.EasyExcel;
    3. import java.util.ArrayList;
    4. import java.util.List;
    5. public class TestEasyExcel {
    6. public static void main(String[] args) {
    7. String filename="D:\\write.xlsx";
    8. // EasyExcel.write(filename,DemoData.class).sheet("学生列表").doWrite(getData());
    9. /**
    10. * 4.读取excel
    11. * 读取filename,利用监听器,把每行内容输出
    12. */
    13. EasyExcel.read(filename,DemoData.class,new ExcelListener()).sheet().doRead();
    14. }
    15. /**
    16. * 3.返回含有数据的list
    17. */
    18. private static List getData(){
    19. ArrayList list = new ArrayList<>();
    20. for (int i = 0; i < 10; i++) {
    21. DemoData data = new DemoData();
    22. data.setSno(i);
    23. data.setSname("Lucy"+i);
    24. list.add(data);
    25. }
    26. return list;
    27. }
    28. }

     读取Excel文件的监听器,监听我们的fileName

    1. package com.atguigu.demo.excel;
    2. import com.alibaba.excel.context.AnalysisContext;
    3. import com.alibaba.excel.event.AnalysisEventListener;
    4. import org.springframework.stereotype.Component;
    5. import java.util.Map;
    6. @Component
    7. public class ExcelListener extends AnalysisEventListener {
    8. /**
    9. * 1.一行一行读取数据
    10. * @param demoData
    11. * @param analysisContext
    12. */
    13. @Override
    14. public void invoke(DemoData demoData, AnalysisContext analysisContext) {
    15. System.out.println("****"+demoData);
    16. }
    17. /**
    18. * 2.去读表头中信息
    19. * @param
    20. */
    21. @Override
    22. public void invokeHeadMap(Map headMap, AnalysisContext context) {
    23. System.out.println("表头:"+headMap);
    24. }
    25. /**
    26. * 3.读完之后干的事情
    27. * @param analysisContext
    28. */
    29. @Override
    30. public void doAfterAllAnalysed(AnalysisContext analysisContext) {
    31. }
    32. }

    项目结合

    一级分类

    1. package com.atguigu.eduservice.entity.subject;
    2. import lombok.Data;
    3. import java.io.Serializable;
    4. import java.util.ArrayList;
    5. import java.util.List;
    6. //一级分类
    7. @Data
    8. public class OneSubject implements Serializable {
    9. private String id;
    10. private String title;
    11. /**
    12. * 一个一级分类里面有多个二级分类(用集合表示)
    13. */
    14. private List children=new ArrayList<>();
    15. }

    二级分类

    1. package com.atguigu.eduservice.entity.subject;
    2. import lombok.Data;
    3. import java.io.Serializable;
    4. //二级分类
    5. @Data
    6. public class TwoSubject implements Serializable {
    7. private String id;
    8. private String title;
    9. }

    控制层上传Excel文件读取课程

    1. @RestController
    2. @RequestMapping("/eduservice/subject")
    3. @CrossOrigin
    4. public class EduSubjectController {
    5. @Autowired
    6. private EduSubjectService subjectService;
    7. /**
    8. * 1.添加课程分类
    9. * 获取用户上传过来的文件然后进行读取
    10. * @Param: MultipartFile
    11. */
    12. @PostMapping("addSubject")
    13. public R addSubject(MultipartFile file){
    14. //1.1上传过来的excel文件
    15. subjectService.saveSubject(file,subjectService);
    16. return R.ok();
    17. }
    18. }

    业务层读取Excel

    注意:这里需要注意我们的控制层传入了subjectService,然后业务层中ExcelListener监听器封装了subejectService,需要注意这里出现了相互调用的情况,所以不能都给Spring管理,所以我们没有@AutoWired注入subjectService,而是通过传参的形式

    这里再普及一下课程信息展示的流程(树形):

    1.首先Wrapper封装父id=0的所有数据,也就是一级分类,然后我们再查询父id!=1的分类也就是二级分类——>2.然后我们对一级分类进行封装,将一级分类转为我们封装的OneSubject——>3.然后我们的封装的一级分类集合遍历,每一个一级分类下有一个二级分类集合属性,将二级分类集合遍历,如果二级id为一级父id,就将当前二级分类加入二级分类集合中——>4.最后一级分类添加这个集合,返回一级分类集合

    1. package com.atguigu.eduservice.service.impl;
    2. import com.alibaba.excel.EasyExcel;
    3. import com.atguigu.eduservice.R;
    4. import com.atguigu.eduservice.entity.EduSubject;
    5. import com.atguigu.eduservice.entity.excel.SubjectData;
    6. import com.atguigu.eduservice.entity.subject.OneSubject;
    7. import com.atguigu.eduservice.entity.subject.TwoSubject;
    8. import com.atguigu.eduservice.listener.SubjectExcelListener;
    9. import com.atguigu.eduservice.mapper.EduSubjectMapper;
    10. import com.atguigu.eduservice.service.EduSubjectService;
    11. import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
    12. import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
    13. import org.springframework.beans.BeanUtils;
    14. import org.springframework.stereotype.Service;
    15. import org.springframework.web.bind.annotation.GetMapping;
    16. import org.springframework.web.multipart.MultipartFile;
    17. import java.io.InputStream;
    18. import java.util.ArrayList;
    19. import java.util.List;
    20. import java.util.stream.Collectors;
    21. /**
    22. *

    23. * 课程科目 服务实现类
    24. *

    25. *
    26. * @author testjava
    27. * @since 2022-07-11
    28. */
    29. @Service
    30. public class EduSubjectServiceImpl extends ServiceImpl implements EduSubjectService {
    31. /**
    32. * 1.添加课程分类,需要读取excel文件
    33. *
    34. * @param file 注意这里new的listener,我们传入service目的是自动注入会造成循环依赖,listener调用service,service调用listener,所以不能使用同一个service
    35. */
    36. @Override
    37. public void saveSubject(MultipartFile file, EduSubjectService subjectService) {
    38. try {
    39. InputStream in = file.getInputStream();
    40. EasyExcel.read(in, SubjectData.class, new SubjectExcelListener(subjectService)).sheet().doRead();
    41. } catch (Exception e) {
    42. e.printStackTrace();
    43. }
    44. }
    45. /**
    46. * 2.获取课程信息
    47. *
    48. * @return
    49. */
    50. @Override
    51. public List getAllOneTwoSubject() {
    52. //1.查询所有的一级分类
    53. QueryWrapper wrapper = new QueryWrapper<>();
    54. wrapper.eq("parent_id", "0");
    55. List oneSubjectList = this.list(wrapper);
    56. //2.查询所有的二级分类
    57. QueryWrapper wrapperTwo = new QueryWrapper<>();
    58. wrapperTwo.ne("parent_id", "0");
    59. List twoSubjectList = this.list(wrapperTwo);
    60. //3.封装所有的一级分类
    61. /**
    62. * 查询出来所有的一级分类list集合遍历得到每个一级对象,获取每个一级分类对象值
    63. * 然后封装到List
    64. */
    65. List finalSubjectList = oneSubjectList.stream().map(eduSubject -> {
    66. OneSubject oneSubject = new OneSubject();
    67. BeanUtils.copyProperties(eduSubject, oneSubject);
    68. return oneSubject;
    69. }).collect(Collectors.toList());
    70. //4.一级分类封装所有的二级分类
    71. for (OneSubject oneSubject : finalSubjectList) {
    72. ArrayList twoFinalSubjectList = new ArrayList<>();
    73. for (EduSubject subject : twoSubjectList) {
    74. if(subject.getParentId().equals(oneSubject.getId())){
    75. TwoSubject twoSubject = new TwoSubject();
    76. BeanUtils.copyProperties(subject,twoSubject);
    77. twoFinalSubjectList.add(twoSubject);
    78. }
    79. }
    80. oneSubject.setChildren(twoFinalSubjectList);
    81. }
    82. return finalSubjectList;
    83. }
    84. }

    Excel的监听器

     1.首先,是两个分类的判断方法,判断两个分类是否存在,并且返回——>2.如果不为空就返回,如果为空就进行添加——>3.ExcelEasy是一行一行读取,传入SubjectData实体类,里面封装了一级分类和二级分类

    1. package com.atguigu.eduservice.entity.excel;
    2. import com.alibaba.excel.annotation.ExcelProperty;
    3. import lombok.Data;
    4. @Data
    5. public class SubjectData {
    6. //一级分类和二级分类
    7. @ExcelProperty(index = 0)
    8. private String oneSubjectName;
    9. @ExcelProperty(index = 1)
    10. private String twoSubjectName;
    11. }
    1. package com.atguigu.eduservice.listener;
    2. import com.alibaba.excel.context.AnalysisContext;
    3. import com.alibaba.excel.event.AnalysisEventListener;
    4. import com.atguigu.eduservice.entity.EduSubject;
    5. import com.atguigu.eduservice.entity.excel.SubjectData;
    6. import com.atguigu.eduservice.exceptionHandler.GuliException;
    7. import com.atguigu.eduservice.service.EduSubjectService;
    8. import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
    9. /**
    10. * 通过监听器来进行读和存储
    11. */
    12. public class SubjectExcelListener extends AnalysisEventListener {
    13. /**
    14. * 1.SubjectExcelListener不能交给Spring管理,不然会造成循环依赖
    15. */
    16. public EduSubjectService subjectService;
    17. //手动传subjectService
    18. public SubjectExcelListener() {}
    19. public SubjectExcelListener(EduSubjectService subjectService) {
    20. this.subjectService = subjectService;
    21. }
    22. /**
    23. * 2.监听获取excel中一行行数据
    24. * @param subjectData
    25. * @param analysisContext
    26. */
    27. @Override
    28. public void invoke(SubjectData subjectData, AnalysisContext analysisContext) {
    29. //2.1判断数据是否为空
    30. if(subjectData==null){
    31. throw new GuliException(20001,"文件数据为空");
    32. }
    33. //2.2一行行读取(一行一列:一级分类),每次读取两个值,一个一级分类,一个二级分类
    34. EduSubject existOneSubject = this.existOneSubject(subjectService, subjectData.getOneSubjectName());
    35. if(existOneSubject==null){
    36. //没有相同的一级分类,我们添加新的一级分类
    37. existOneSubject = new EduSubject();
    38. existOneSubject.setParentId("0");
    39. existOneSubject.setTitle(subjectData.getOneSubjectName());
    40. subjectService.save(existOneSubject);
    41. }
    42. //2.3获取一级分类id
    43. String pid = existOneSubject.getId();
    44. //2.4添加二级分类,需要判断二级分类是否重复
    45. EduSubject existTwoSubject = this.existTwoSubject(subjectService, subjectData.getTwoSubjectName(), pid);
    46. if(existTwoSubject==null){
    47. existTwoSubject=new EduSubject();
    48. existTwoSubject.setParentId(pid);
    49. existTwoSubject.setTitle(subjectData.getTwoSubjectName());
    50. subjectService.save(existTwoSubject);
    51. }
    52. }
    53. /**
    54. * 3.一级title的判断
    55. * 这里用subjectService目的可能其他地方还需要调用
    56. * @param
    57. */
    58. private EduSubject existOneSubject(EduSubjectService subjectService,String name){
    59. QueryWrapper wrapper = new QueryWrapper<>();
    60. wrapper.eq("title",name);
    61. wrapper.eq("parent_id","0");
    62. EduSubject oneSubject = subjectService.getOne(wrapper);
    63. return oneSubject;
    64. }
    65. /**
    66. * 3.二级分类的判断,得到二级标签
    67. * @param subjectService
    68. * @param name:课程名称
    69. * @param pid:课程号
    70. */
    71. private EduSubject existTwoSubject(EduSubjectService subjectService,String name,String pid){
    72. QueryWrapper wrapper = new QueryWrapper<>();
    73. wrapper.eq("title",name);
    74. wrapper.eq("parent_id",pid);
    75. EduSubject oneSubject = subjectService.getOne(wrapper);
    76. return oneSubject;
    77. }
    78. @Override
    79. public void doAfterAllAnalysed(AnalysisContext analysisContext) {
    80. }
    81. }

     

  • 相关阅读:
    HTTP 接口测试的流程
    LLM优化:开源星火13B显卡及内存占用优化
    22-06-28 西安 redis(02) 持久化机制、入门使用、事务控制、主从复制机制
    lambda表达式
    Linux命令基础
    哈希表学习
    ArcGIS Engine基础(29)之加载arcgis server切片地图服务
    软件测试需要学多久 ?这篇文章告诉你答案..
    git学习(一)
    JMeter 性能测试基本过程及示例
  • 原文地址:https://blog.csdn.net/weixin_57128596/article/details/126067857