SpringBoot整合EasyExcel实现导入导出功能
作者:皓月清风
EasyExcel是一个基于Java的、快速、简洁、解决大文件内存溢出的Excel处理工具,他能让你在不用考虑性能、内存的等因素的情况下,快速完成Excel的读、写等功能,本文就给大家介绍一下SpringBoot整合EasyExcel实现导入导出功能的方法,需要的朋友可以参考下
EasyExcel是什么
EasyExcel是一个基于Java的、快速、简洁、解决大文件内存溢出的Excel处理工具。
他能让你在不用考虑性能、内存的等因素的情况下,快速完成Excel的读、写等功能。
相关网站
官网 https://easyexcel.opensource.alibaba.com/
GitHub https://github.com/alibaba/easyexcel
实现
pom依赖导入
<dependency> <groupId>com.alibaba</groupId> <artifactId>easyexcel</artifactId> <version>3.3.2</version> </dependency>
excel数据
一共包含姓名,手机号,性别,地址,状态,注册时间6列,共50条数据
数据库表结构
实体类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; /** * <p> * 用户实体类 * </p> * * @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; /** * <p> * 用户excel实体类 * </p> * * @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; /** * <p> * 用户excel监听类 * </p> * * @author yurenwei * @since 2023/9/7 */ @Slf4j public class UserExcelListener implements ReadListener<UserExcelDTO> { /** * 每隔10条数据存储数据库,然后清理List,方便内存回收 * */ private static final int BATCH_COUNT = 10; /** * 缓存的数据 */ private List<UserExcelDTO> 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<User> 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("存储数据库成功!"); } }
启动项目测试导入
控制台打印信息
查看数据库是否成功导入数据
可见50条都被成功导入到数据库表当中,并且数据都是正确的。
接下来实现导出
controller导出方法
@ApiOperation("导出") @PostMapping("/export") public void export(HttpServletResponse response){ userService.export(response); }
service导出方法
/** * 导出 * * @param response 响应 */ public void export(HttpServletResponse response) { // 查询所有用户 List<User> list = iUserService.list(); // 转换数据 List<UserExcelDTO> 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; /** * <p> * excel工具类 * </p> * * @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(); } } }
测试导出
下载excel文件查看
测试导出excel 列名和数据都正确
至此,SpringBoot整合EasyExcel实现导入导出完成了,通过整合测试发现,使用EasyExcel还是挺方便的。
以上就是SpringBoot整合EasyExcel实现导入导出功能的详细内容,更多关于SpringBoot整合EasyExcel的资料请关注脚本之家其它相关文章!