使用EasyExcel实现导入、导出工具类

1.引入依赖:

<dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>easyexcel</artifactId>
            <version>${easyexcel.version}</version>
        </dependency>
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>easyexcel-core</artifactId>
            <version>3.3.4</version>
            <scope>compile</scope>
        </dependency>

2.监听器(用于解析和存储到数据库):

@Slf4j
public class DemoDataListener<T> extends AnalysisEventListener<T> {

    /**
     *
     * 每隔5条存储数据库,实际使用中可以100条,然后清理list ,方便内存回收
     */
    private static final int BATCH_COUNT = 100;
    /**
     * 缓存的数据
     */
    private List<T> cachedDataList = ListUtils.newArrayListWithExpectedSize(BATCH_COUNT);
    /**
     * 假设这个是一个DAO,当然有业务逻辑这个也可以是一个service。当然如果不用存储这个对象没用。
     */
    private BaseService demoDAO;

//    public DemoDataListener() {
//        // 这里是demo,所以随便new一个。实际使用如果到了spring,请使用下面的有参构造函数
//        demoDAO = new DemoDAO();
//    }

    /**
     * 如果使用了spring,请使用这个构造方法。每次创建Listener的时候需要把spring管理的类传进来
     *
     * @param demoDAO
     */
    public DemoDataListener(BaseService demoDAO) {
        this.demoDAO = demoDAO;
    }

    /**
     * 这个每一条数据解析都会来调用
     *
     * @param data    one row value. Is is same as {@link AnalysisContext#readRowHolder()}
     * @param context
     */
    @Override
    public void invoke(T data, AnalysisContext context) {
        log.info("解析到一条数据:{}", JSON.toJSONString(data));
        cachedDataList.add(data);
        // 达到BATCH_COUNT了,需要去存储一次数据库,防止数据几万条数据在内存,容易OOM
        if (cachedDataList.size() >= BATCH_COUNT) {
            saveData();
            // 存储完成清理 list
            cachedDataList = ListUtils.newArrayListWithExpectedSize(BATCH_COUNT);
        }
    }

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

    /**
     * 加上存储数据库
     */
    private void saveData() {
        log.info("{}条数据,开始存储数据库!", cachedDataList.size());
        demoDAO.insertBatch(cachedDataList);
        log.info("存储数据库成功!");
    }
}

3.excel工具类:

/**
 * excel工具类
 *
 */
public class ExcelUtils {

    /**
     * Excel导出
     *
     * @param response  response
     * @param fileName  文件名
     * @param sheetName sheetName
     * @param list      数据List
     * @param pojoClass 对象Class
     */
    public static void exportExcel(HttpServletResponse response, String fileName, String sheetName, List<?> list,
                                   Class<?> pojoClass) throws IOException {
        if (StrUtil.isBlank(fileName)) {
            //当前日期
            fileName = DateUtils.format(new Date());
        }

        response.setContentType("application/vnd.ms-excel");
        response.setCharacterEncoding("UTF-8");
        fileName = URLUtil.encode(fileName, StandardCharsets.UTF_8);
        response.setHeader("Content-disposition", "attachment;filename=" + fileName + ".xlsx");
        EasyExcel.write(response.getOutputStream(), pojoClass).registerConverter(new LongStringConverter()).registerConverter(new DateDateConverter()).sheet(sheetName).doWrite(list);
    }

    /**
     * Excel导出,先sourceList转换成List<targetClass>,再导出
     *
     * @param response    response
     * @param fileName    文件名
     * @param sheetName   sheetName
     * @param sourceList  原数据List
     * @param targetClass 目标对象Class
     */
    public static void exportExcelToTarget(HttpServletResponse response, String fileName, String sheetName, List<?> sourceList,
                                           Class<?> targetClass) throws Exception {
        List targetList = new ArrayList<>(sourceList.size());
        for (Object source : sourceList) {
            Object target = targetClass.newInstance();
            BeanUtils.copyProperties(source, target);
            targetList.add(target);
        }

        exportExcel(response, fileName, sheetName, targetList, targetClass);
    }

    /**
     * 导入excel(适合excel中表头和实体类中一致的情况,无需手动插入数据库)
     * @param excel excel文件
     * @param pojoClass 对象Class
     * @param baseService 实体类对应service
     */
    public static void importExcel(MultipartFile excel, Class<?> pojoClass, BaseService baseService) throws IOException {
        EasyExcel.read(excel.getInputStream(), pojoClass, new DemoDataListener<>(baseService))
                .sheet()
                .headRowNumber(1)
                .doRead();
    }

    /**
     * 读取excel
     * @param excel excel文件
     * @param pojoClass 对象Class
     */
    public static <T> List<T> readExcel(MultipartFile excel, Class<?> pojoClass) throws IOException {
        return EasyExcelFactory
                .read(excel.getInputStream())
                .sheet()
                .head(pojoClass)
                .doReadSync();
    }

}

4.实例;

@PostMapping("/export")
    @ApiOperation("导出")
    public void exportExcel(HttpServletResponse response, @RequestBody List<BaseContentVo> baseContentVos) {
        try {
            ExcelUtils.exportExcelToTarget(response, "基础数据", "", baseContentVos, BaseContent.class);
        } catch (Exception e) {
            throw new GeneralException("导出失败");
        }
    }

    @GetMapping("/export/template")
    @ApiOperation("导出模版")
    public void exportExcelTemplate(HttpServletResponse response) {
        try {
            ExcelUtils.exportExcelToTarget(response, "基础数据", "", Collections.emptyList(), BaseTechnologyDto.class);
        } catch (Exception e) {
            throw new GeneralException("导出模版失败");
        }
    }

    @PostMapping("/import")
    @ApiOperation("导入")
    public Result importExcel(MultipartFile file) {
        try {
            List<BaseContentDto> dtoList = ExcelUtils.readExcel(file, BaseContentDto.class);
            for (BaseContentDto dto : dtoList) {
                DefaultValueUtils.applyDefaultValues(dto);
                baseContentService.add(dto);
            }
        } catch (IOException e) {
            throw new GeneralException("导入失败");
        }
        return new Result<>();
    }
  • 4
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值