Springboot 集成 EasyExcel (2.1.1)

1、引入Maven以来

<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>easyexcel</artifactId>
    <version>2.1.1</version>
</dependency>
<dependency>
    <groupId>org.apache.poi</groupId>
    <artifactId>poi</artifactId>
    <version>3.17</version>
</dependency>

注意:POI的版本必须为3.17

2、编写模板类


import com.alibaba.excel.annotation.ExcelProperty;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;

/**
 * @author zyq
 * @Description ExcelProperty为表头名称
 * @createTime 2021年01月22日 19:52:00
 */
@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
public class ExcelDataVO {

    @ExcelProperty(value = "编号", index = 0)
    private Integer id;

    @ExcelProperty(value = "姓名", index = 1)
    private String name;

}

3、EasyExcel工具类

import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.ExcelReader;
import com.alibaba.excel.event.AnalysisEventListener;
import com.alibaba.excel.read.metadata.ReadSheet;
import com.alibaba.excel.support.ExcelTypeEnum;
import org.springframework.web.multipart.MultipartFile;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.URLEncoder;
import java.util.List;

/**
 * @author zyq
 * @Description
 * @createTime 2021年01月22日 20:04:00
 */
public class ExcelUtils {

    /**
     * 导出Excel
     * @param response
     * @param list 数据
     * @param fileName 文件名称
     * @param sheetName 表名
     * @param clazz 指定导出模板类的类型
     */
    public static void writeExcel(HttpServletResponse response, List<?> list,
                                  String fileName, String sheetName, Class<?> clazz){
        EasyExcel.write(getOutputStream(fileName, response), clazz)
                .excelType(ExcelTypeEnum.XLSX)
                .sheet(sheetName)
                .doWrite(list);
    }


    /**
     * 读取Excel中的数据
     * @param file
     * @param clazz
     * @param listener
     */
    public static void readExcel(MultipartFile file, Class<?> clazz, AnalysisEventListener<?> listener) {
        ExcelReader excelReader = null;
        try {
            excelReader = EasyExcel.read(getInputStream(file), clazz, listener).build();
            ReadSheet readSheet = EasyExcel.readSheet(0).build();
            excelReader.read(readSheet);
        } finally {
            if (excelReader != null) {
                // 这里千万别忘记关闭,读的时候会创建临时文件,到时磁盘会崩的
                excelReader.finish();
            }
        }
    }

    /**
     * 导出文件时为Writer生成OutputStream
     * @param fileName
     * @param response
     * @return
     */
    private static OutputStream getOutputStream(String fileName, HttpServletResponse response) {
        try {
            fileName = URLEncoder.encode(fileName, "UTF-8");
            response.setContentType("application/vnd.ms-excel");
            response.setCharacterEncoding("utf8");
            response.setHeader("Content-Disposition", "attachment; filename=" + fileName + ".xlsx");
            response.setHeader("Pragma", "public");
            response.setHeader("Cache-Control", "no-store");
            response.addHeader("Cache-Control", "max-age=0");
            return response.getOutputStream();
        } catch (IOException e) {
            throw new ApiException("导出excel表格失败!");
        }
    }


    /**
     * 导入文件时为Reader生成InputStream
     * @param file
     * @return
     */
    private static InputStream getInputStream(MultipartFile file) {
        try {
            return file.getInputStream();
        } catch (IOException e) {
            throw new ApiException("导入excel表格数据失败!");
        }
    }
}

5、导入Excel时需要监听器

import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.event.AnalysisEventListener;
import com.guli.service_edu.entity.EduTeacher;
import com.guli.service_edu.mapper.EduTeacherMapper;
import com.guli.service_edu.vo.ExcelDataVO;
import lombok.extern.slf4j.Slf4j;

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

/**
 * @author zyq
 * @Description
 * ExcelDataListener 不能被spring管理,
 * 要每次读取excel都要new,然后里面用到spring可以构造方法传进
 * 每次创建Listener的时候需要把spring管理的类传进来
 * @createTime 2021年01月23日 14:23:00
 */
@Slf4j
public class ExcelDataListener extends AnalysisEventListener<ExcelDataVO> {


    /**
     * 每隔5条存储数据库,实际使用中可以3000条,然后清理list ,方便内存回收
     */
    private static final int BATCH_COUNT = 5;
    List<ExcelDataVO> list = new ArrayList<>();

    /**
     * 每次创建Listener的时候需要把spring管理的类传进来
     */
    private final EduTeacherMapper teacherMapper;
    public ExcelDataListener(EduTeacherMapper eduTeacherMapper){
        this.teacherMapper = eduTeacherMapper;
    }

    /**
     * 每一条数据解析都会来调用
     * @param data
     * @param context
     */
    @Override
    public void invoke(ExcelDataVO data, AnalysisContext context) {
        log.info("【解析Excel数据】");
        list.add(data);
        // 达到BATCH_COUNT了,需要去存储一次数据库,防止数据几万条数据在内存,容易OOM
        if (list.size() >= BATCH_COUNT) {
            saveData();
            // 存储完成清理 list
            list.clear();
        }

    }

    /**
     * 所有数据解析完成了 都会来调用
     * @param context
     */
    @Override
    public void doAfterAllAnalysed(AnalysisContext context) {
        // 这里也要保存数据,确保最后遗留的数据也存储到数据库
        saveData();
        log.info("所有数据解析完成!");
    }


    /**
     * 加上存储数据库, 这里批量插入需要写一个服务层进行批量插入,
     * 避免在循环体中调用持久层的insert方法
     */
    private void saveData() {
        log.info("{}条数据,开始存储数据库!", list.size());
        for (ExcelDataVO vo : list) {
            EduTeacher eduTeacher = new EduTeacher();
            eduTeacher.setAvatar(vo.getId() + vo.getName());
            eduTeacher.setName(vo.getName());
            eduTeacher.setLevel(vo.getId());
            eduTeacher.setSort(vo.getId());
            eduTeacher.setIntro(vo.getName());
            teacherMapper.insert(eduTeacher);
        }
        log.info("存储数据库成功!");
    }
}

4、控制层调用

@GetMapping("/excel")
public void excel(HttpServletResponse response){
    List<ExcelDataVO> list = new ArrayList<>();
    for (int i = 1; i < 10; i++) {
        list.add(ExcelDataVO.builder()
                .id(i)
                .name("🐖👁掏" + i)
                .build());
    }
    try {
        ExcelUtils.writeExcel(response, list, "fileName", "sheetName", ExcelDataVO.class);
    }catch (Exception e) {
        throw new ApiException("EXCEL DOWNLOAD ERROR!");
    }
}

@ApiOperation("导入数据")
@PostMapping("/excel")
public void addExcel(MultipartFile file){
    try {
        ExcelUtils.readExcel(file, ExcelDataVO.class, new ExcelDataListener(eduTeacherMapper));
    }catch (Exception e) {
        throw new ApiException("EXCEL UPLOAD ERROR!");
    }
}

注意:不需要对response.getOutputStream()进行flush和close,见参考文档

HttpServletResponse输入输出流是否需要flush close

EasyExcel官方文档地址 EasyExcel

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
好的,很高兴回答您的问题。SpringBoot集成EasyExcel可以大大简化Excel文件的读写操作。您可以按照以下步骤进行集成: 1. 添加EasyExcel依赖 在pom.xml文件中添加以下依赖: ```xml <dependency> <groupId>com.alibaba</groupId> <artifactId>easyexcel</artifactId> <version>2.2.6</version> </dependency> ``` 2. 添加EasyExcel配置 您可以添加以下配置来启用EasyExcel: ```java @Configuration public class EasyExcelConfig { @Bean public EasyExcelTemplate easyExcelTemplate() { // 设置读取文件的最大行数 EasyExcelTemplate easyExcelTemplate = new EasyExcelTemplate(); ReaderOption readerOption = new ReaderOption(); readerOption.setCount(10000); easyExcelTemplate.setReaderOption(readerOption); return easyExcelTemplate; } } ``` 3. 编写Excel文件读写代码 您可以按照以下代码编写读取和写入Excel文件的代码: ```java @Component public class ExcelService { @Autowired private EasyExcelTemplate easyExcelTemplate; /** * 写出数据到Excel文件 */ public void writeExcel(List<Object> data, String filePath) { ExcelWriter excelWriter = easyExcelTemplate.getWriter(filePath); WriteSheet writeSheet = EasyExcel.writerSheet(0).build(); // 设置表头和数据 excelWriter.write(data, writeSheet); // 输出文件 excelWriter.finish(); } /** * 读取Excel文件 */ public void readExcel(String filePath) { ExcelReader excelReader = easyExcelTemplate.getReader(filePath); List<Object> data = new ArrayList<>(); ReadSheet readSheet = EasyExcel.readerSheet(0).build(); excelReader.read(readSheet).forEach(object -> data.add(object)); // 输出数据 System.out.println(data); } } ``` 通过这样的方式,您就可以很方便地读写Excel文件了。希望能对您有所帮助。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

it00zyq

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值