SpringBoot整合EasyExcel实现导入导出

1、EasyExcel是什么

EasyExcel是一个基于Java的、快速、简洁、解决大文件内存溢出的Excel处理工具。
他能让你在不用考虑性能、内存的等因素的情况下,快速完成Excel的读、写等功能。

2、相关网站

官网icon-default.png?t=N7T8https://easyexcel.opensource.alibaba.com/

GitHubicon-default.png?t=N7T8https://github.com/alibaba/easyexcel

3、实现导入

pom依赖导入


    com.alibaba
    easyexcel
    3.3.2

excel数据

SpringBoot整合EasyExcel实现导入导出_第1张图片

一共包含姓名,手机号,性别,地址,状态,注册时间6列,共50条数据

数据库表结构

SpringBoot整合EasyExcel实现导入导出_第2张图片

实体类User

package com.example.springbootdemo.entity;

import com.baomidou.mybatisplus.annotation.*;
import com.example.springbootdemo.enums.GenderEnum;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateTimeDeserializer;
import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateTimeSerializer;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.experimental.Accessors;

import java.io.Serializable;
import java.time.LocalDateTime;

/**
 * 

* 用户实体类 *

* * @author yurenwei * @since 2023/9/7 */ @ApiModel(value = "用户参数", description = "用户参数") @Data @Accessors(chain = true) @TableName("user") public class User implements Serializable { private static final long serialVersionUID = 1L; /** * 主键id */ @ApiModelProperty(value = "主键id") @TableId(value = "id", type = IdType.ASSIGN_ID) private Long id; /** * 姓名 */ @ApiModelProperty(value = "姓名") private String userName; /** * 手机号 */ @ApiModelProperty(value = "手机号") private String phone; /** * 性别 */ @ApiModelProperty(value = "性别") private GenderEnum gender; /** * 地址 */ @ApiModelProperty(value = "地址") private String address; /** * 状态(0、禁用1、启用) */ @ApiModelProperty(value = "状态(0、禁用1、启用)") private Boolean status; /** * 注册时间 */ @ApiModelProperty(value = "注册时间") @JsonDeserialize(using = LocalDateTimeDeserializer.class) @JsonSerialize(using = LocalDateTimeSerializer.class) @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") private LocalDateTime registerTime; /** * 创建人 */ @ApiModelProperty(value = "创建人") private Long createBy; /** * 创建时间 */ @ApiModelProperty(value = "创建时间") @JsonDeserialize(using = LocalDateTimeDeserializer.class) @JsonSerialize(using = LocalDateTimeSerializer.class) @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") @TableField(fill = FieldFill.INSERT) private LocalDateTime createTime; /** * 修改人 */ @ApiModelProperty(value = "修改人") private Long updateBy; /** * 修改时间 */ @ApiModelProperty(value = "修改时间") @JsonDeserialize(using = LocalDateTimeDeserializer.class) @JsonSerialize(using = LocalDateTimeSerializer.class) @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") @TableField(fill = FieldFill.INSERT_UPDATE) private LocalDateTime updateTime; /** * 是否删除(0、否1、是) */ @ApiModelProperty(value = "是否删除(0、否1、是)") private Boolean isDeleted; }

controller导入方法

@ApiOperation("导入")
@PostMapping("/importUser")
public Result importUser(@RequestParam(value = "file") MultipartFile file){
    userService.importUser(file);
    return Result.ok();
}

service导入方法

/**
 * 导入excel
 *
 * @param file excel文件
 */
public void importUser(MultipartFile file) {
    try {
        EasyExcel.read(file.getInputStream(), UserExcelDTO.class, new UserExcelListener(iUserService))
                .sheet(0)
                .headRowNumber(1)
                .doRead();
    } catch (IOException e) {
        log.error("导入用户数据异常:{}",e.getMessage());
        e.printStackTrace();
    }
}

excel对应实体类

package com.example.springbootdemo.dto;

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

import java.io.Serializable;
import java.time.LocalDateTime;

/**
 * 

* 用户excel实体类 *

* * @author yurenwei * @since 2023/9/7 */ @Data public class UserExcelDTO implements Serializable { private static final long serialVersionUID = 1L; /** * 姓名 */ @ExcelProperty(value = "姓名",index = 0) private String userName; /** * 手机号 */ @ExcelProperty(value = "手机号",index = 1) private String phone; /** * 性别 */ @ExcelProperty(value = "性别",index = 2) private String gender; /** * 地址 */ @ExcelProperty(value = "地址",index = 3) private String address; /** * 状态(0、禁用1、启用) */ @ExcelProperty(value = "状态",index = 4) private String status; /** * 注册时间 */ @ExcelProperty(value = "注册时间",index = 5) @DateTimeFormat("yyyy-MM-dd HH:mm:ss") private LocalDateTime registerTime; }

此处注意# @Accessors(chain = true)与EasyExcel不兼容,不要增加此注解,要不导入数据为空

创建读取excel监听类

package com.example.springbootdemo.listener;

import cn.hutool.core.util.IdUtil;
import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.read.listener.ReadListener;
import com.alibaba.excel.util.ListUtils;
import com.alibaba.fastjson.JSON;
import com.example.springbootdemo.dto.UserExcelDTO;
import com.example.springbootdemo.entity.User;
import com.example.springbootdemo.enums.GenderEnum;
import com.example.springbootdemo.mybatisplus.IUserService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;

import java.util.List;
import java.util.stream.Collectors;

/**
 * 

* 用户excel监听类 *

* * @author yurenwei * @since 2023/9/7 */ @Slf4j public class UserExcelListener implements ReadListener { /** * 每隔10条数据存储数据库,然后清理List,方便内存回收 * */ private static final int BATCH_COUNT = 10; /** * 缓存的数据 */ private List cacheList = ListUtils.newArrayListWithExpectedSize(BATCH_COUNT); private IUserService iUserService; public UserExcelListener(IUserService iUserService){ this.iUserService = iUserService; } /** * 每一条数据解析都会调用 * * @param user * @param analysisContext */ @Override public void invoke(UserExcelDTO user, AnalysisContext analysisContext) { log.info("解析到一条数据user:{}", JSON.toJSONString(user)); cacheList.add(user); // 达到BATCH_COUNT了,需要去存储一次数据库,防止数据几万条数据在内存,容易OOM if(cacheList.size()>=BATCH_COUNT){ // 保存数据 saveData(); // 存储完成清理list cacheList = ListUtils.newArrayListWithExpectedSize(BATCH_COUNT); } } /** * 所有数据都解析完了才会调用 * * @param analysisContext */ @Override public void doAfterAllAnalysed(AnalysisContext analysisContext) { // 这里也要保存数据,确保最后遗留的数据也存储到数据库 saveData(); log.info("所有数据解析完成!"); } /** * 保存数据 */ public void saveData(){ log.info("一共{}条数据,开始存储数据库!",cacheList.size()); if(CollectionUtils.isNotEmpty(cacheList)){ List userList = cacheList.stream().map(item -> new User() .setId(IdUtil.getSnowflakeNextId()) .setUserName(item.getUserName()) .setPhone(item.getPhone()) .setGender("男".equals(item.getGender())? GenderEnum.MALE:GenderEnum.FEMALE) .setAddress(item.getAddress()) .setRegisterTime(item.getRegisterTime()) .setStatus("启用".equals(item.getStatus()))) .collect(Collectors.toList()); // 批量保存 iUserService.saveBatch(userList); } log.info("存储数据库成功!"); } }

启动项目测试导入

SpringBoot整合EasyExcel实现导入导出_第3张图片

控制台打印信息

查看数据库是否成功导入数据

可见50条都被成功导入到数据库表当中,并且数据都是正确的。

4、接下来实现导出

controller导出方法

@ApiOperation("导出")
@PostMapping("/export")
public void export(HttpServletResponse response){
    userService.export(response);
}

service导出方法

/**
 * 导出
 *
 * @param response 响应
 */
public void export(HttpServletResponse response) {
    // 查询所有用户
    List list = iUserService.list();
    // 转换数据
    List excelList = list.stream().map(item ->
            {
                UserExcelDTO user = new UserExcelDTO();
                user.setUserName(item.getUserName());
                user.setPhone(item.getPhone());
                user.setGender(GenderEnum.MALE.equals(item.getGender())?"男":"女");
                user.setAddress(item.getAddress());
                user.setStatus(item.getStatus()?"启用":"禁用");
                user.setRegisterTime(item.getRegisterTime());

                return user;
            })
            .collect(Collectors.toList());
    // 调用工具类导出
    ExcelUtil.exportExcel("用户数据","用户",excelList,UserExcelDTO.class,response);
}

导出excel工具类

package com.example.springbootdemo.util;

import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.support.ExcelTypeEnum;
import lombok.extern.slf4j.Slf4j;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.util.List;

/**
 * 

* excel工具类 *

* * @author yurenwei * @since 2023/9/14 */ @Slf4j public class ExcelUtil { /** * 导出excel * * @param fileName excel文件名称 * @param sheetName excel sheet名称 * @param list 数据 * @param clazz * @param response */ public static void exportExcel(String fileName, String sheetName, List list, Class clazz, HttpServletResponse response){ ServletOutputStream outputStream; try { response.setContentType("application/vnd.ms-excel"); response.setCharacterEncoding("utf8"); response.setHeader("Content-Disposition", "attachment; filename=" + fileName + ".xlsx"); outputStream = response.getOutputStream(); EasyExcel.write(outputStream) .head(clazz) .excelType(ExcelTypeEnum.XLSX) .sheet(sheetName) .doWrite(list); outputStream.flush(); } catch (Exception e) { log.error("导出excel异常:{}",e.getMessage()); e.printStackTrace(); } } }

测试导出

SpringBoot整合EasyExcel实现导入导出_第4张图片

下载excel文件查看

SpringBoot整合EasyExcel实现导入导出_第5张图片

通过测试导出excel 列名和数据都正确

5、总结

至此,SpringBoot整合EasyExcel实现导入导出完成了,通过整合测试发现,使用EasyExcel还是挺方便的。

你可能感兴趣的:(Java,SpringBoot,spring,boot,后端,java)