Features:
1. Java domain analysis and Excel generation are more famous frameworks such as Apache poi, jxl, etc. But they all have a serious problem: they consume a lot of memory. If the concurrency of your system is not large, it may be okay, but once the concurrency increases, it will definitely cause OOM or frequent full gc of the JVM.
2. EasyExcel is an open source excel processing framework from Alibaba, which is famous for its simplicity of use and memory saving. The main reason why EasyExcel can greatly reduce the memory usage is that when parsing Excel, the file data is not loaded into the memory all at once. Instead, the data is read line by line from the disk and parsed one by one.
3. EasyExcel adopts a line-by-line analysis mode, and notifies the processing (AnalysisEventListener) of the analysis results of a line in the observer mode.
1. Data import: reduce the input workload
2. Data export: statistical information archiving
3. Data transmission: Data transmission between heterogeneous systems
sql
CREATE TABLE `edu_subject` ( `id` char(19) NOT NULL COMMENT "课程类别ID", `title` varchar(10) NOT NULL COMMENT "类别名称", `parent_id` char(19) NOT NULL DEFAULT "0" COMMENT "父ID", `sort` int unsigned NOT NULL DEFAULT "0" COMMENT "排序字段", `gmt_create` datetime NOT NULL COMMENT "创建时间", `gmt_modified` datetime NOT NULL COMMENT "更新时间", PRIMARY KEY (`id`), KEY `idx_parent_id` (`parent_id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci ROW_FORMAT=COMPACT COMMENT="课程科目";
Convert to->
Warm reminder: The following versions cannot be replaced, and it may not work if you change them
<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>
package com.zhz.serviceedu.controller; import com.zhz.common.utils.R; import com.zhz.serviceedu.service.EduSubjectService; import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.CrossOrigin; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import org.springframework.web.multipart.MultipartFile; /** * <p> * 课程科目 前端控制器 * </p> * * @author zhz * @since 2021-07-03 */ @RestController @RequestMapping("/eduservice/subject") @CrossOrigin @Api(tags = "课程科目") public class EduSubjectController { @Autowired private EduSubjectService eduSubjectService; /** * 添加课程分类,获取上传过来的文件,把文件内容读取出来 */ @PostMapping("/addSubject") @ApiOperation(value = "添加课程分类,获取上传过来的文件,把文件内容读取出来") public R addSubject(MultipartFile file){ //上传过来的excel文件 eduSubjectService.saveSubject(file,eduSubjectService); return R.ok(); } }
package com.zhz.serviceedu.service; import com.zhz.serviceedu.entity.EduSubject; import com.baomidou.mybatisplus.extension.service.IService; import org.springframework.web.multipart.MultipartFile; /** * <p> * 课程科目 服务类 * </p> * * @author zhz * @since 2021-07-03 */ public interface EduSubjectService extends IService<EduSubject> { /** * 添加课程信息 * * @author zhz * @date 2021/07/02 02:18 * @param file 文件对象,用于获取excel文件 * @param eduSubjectService 方便监听器部分引用 */ void saveSubject(MultipartFile file, EduSubjectService eduSubjectService); }
package com.zhz.serviceedu.service.impl; import com.alibaba.excel.EasyExcel; import com.zhz.serviceedu.entity.EduSubject; import com.zhz.serviceedu.entity.excel.SubjectData; import com.zhz.serviceedu.listener.SubjectExcelListener; import com.zhz.serviceedu.mapper.EduSubjectMapper; import com.zhz.serviceedu.service.EduSubjectService; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import org.springframework.stereotype.Service; import org.springframework.web.multipart.MultipartFile; import java.io.InputStream; /** * <p> * 课程科目 服务实现类 * </p> * * @author zhz * @since 2021-07-03 */ @Service public class EduSubjectServiceImpl extends ServiceImpl<EduSubjectMapper, EduSubject> implements EduSubjectService { /** * 添加课程信息 * * @param file 文件对象,用于获取excel文件 * @param eduSubjectService * @author zhz * @date 2021/07/02 02:18 */ @Override public void saveSubject(MultipartFile file, EduSubjectService eduSubjectService) { try { //文件输入流 InputStream in = file.getInputStream(); //调用方法进行读取 EasyExcel.read(in, SubjectData.class,new SubjectExcelListener(eduSubjectService)).sheet().doRead(); }catch (Exception e){ e.printStackTrace(); } } }
package com.zhz.serviceedu.listener; import com.alibaba.excel.context.AnalysisContext; import com.alibaba.excel.event.AnalysisEventListener; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.zhz.servicebase.execptionhandler.GuliException; import com.zhz.serviceedu.entity.EduSubject; import com.zhz.serviceedu.entity.excel.SubjectData; import com.zhz.serviceedu.service.EduSubjectService; import lombok.extern.slf4j.Slf4j; import org.springframework.util.StringUtils; /** * @author zhouhengzhe * @Description: excel监听器 * @date 2021/7/3上午2:28 */ @Slf4j public class SubjectExcelListener extends AnalysisEventListener<SubjectData> { /** * 创建有参数构造,传递subjectService用于操作数据库 * 因为SubjectExcelListener不能交给spring去管理,所以需要自己new,不能注入对象 * 此处一定要是public,不然永远获取不到对象 */ public EduSubjectService eduSubjectService; public SubjectExcelListener() { } public SubjectExcelListener(EduSubjectService eduSubjectService) { this.eduSubjectService = eduSubjectService; } /** * 读取excel内容,一行一行进行读取,此处全是业务处理 * @param subjectData * @param analysisContext */ @Override public void invoke(SubjectData subjectData, AnalysisContext analysisContext) { log.info("进入方法调用"); if (StringUtils.isEmpty(subjectData)){ throw new GuliException(20001,"文件数据为空"); } //一行一行去读取excel内容,每次读取有两个值,第一个值为一级分类,第二个值为二级分类 //判断一级分类是否重复 EduSubject existOneSubject = this.existOneSubject(eduSubjectService, subjectData.getOneSubjectName()); if (StringUtils.isEmpty(existOneSubject)){ existOneSubject=new EduSubject(); existOneSubject.setParentId("0"); //一级分类名称 existOneSubject.setTitle(subjectData.getOneSubjectName()); eduSubjectService.save(existOneSubject); } //获取一级分类的pid值 String pid=existOneSubject.getId(); //添加二级分类 // 判断二级分类是否重复 EduSubject existTwoSubject = this.existTwoSubject(eduSubjectService, subjectData.getTwoSubjectName(), pid); if (StringUtils.isEmpty(existTwoSubject)){ existTwoSubject=new EduSubject(); existTwoSubject.setParentId(pid); //二级分类名称 existTwoSubject.setTitle(subjectData.getTwoSubjectName()); eduSubjectService.save(existTwoSubject); } } /** * 读取完成后执行 */ @Override public void doAfterAllAnalysed(AnalysisContext analysisContext) { } /** * 判断一级分类是否重复 * 因为课程的的parent_id为0时,代表是一级分类,并且一级分类数据不重复 * @param eduSubjectService * @param name * @return */ private EduSubject existOneSubject(EduSubjectService eduSubjectService,String name){ QueryWrapper<EduSubject> wrapper=new QueryWrapper<>(); wrapper.eq("title",name); wrapper.eq("parent_id","0"); EduSubject subject = eduSubjectService.getOne(wrapper); return subject; } /** * 判断二级分类是否重复 * * @param eduSubjectService * @param name * @param pid * @return */ private EduSubject existTwoSubject(EduSubjectService eduSubjectService,String name,String pid){ QueryWrapper<EduSubject> wrapper=new QueryWrapper<>(); wrapper.eq("title",name); wrapper.eq("parent_id",pid); EduSubject eduSubject = eduSubjectService.getOne(wrapper); return eduSubject; } }
Because the primary key generation strategy of the entity class generated by mybatisplus is IdType.ID_WORKER, it needs to be modified to IdType.ID_WORKER_STR, otherwise there will be conversion problems
package com.zhz.serviceedu.entity; import com.baomidou.mybatisplus.annotation.FieldFill; import com.baomidou.mybatisplus.annotation.IdType; import java.util.Date; import com.baomidou.mybatisplus.annotation.TableField; import com.baomidou.mybatisplus.annotation.TableId; import java.io.Serializable; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; import lombok.Data; import lombok.EqualsAndHashCode; import lombok.experimental.Accessors; /** * <p> * 课程科目 * </p> * * @author zhz * @since 2021-07-03 */ @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_UPDATE) private Date gmtModified; }
The above is the detailed content of How SpringBoot integrates EasyExcel application. For more information, please follow other related articles on the PHP Chinese website!