SpringBoot整合EasyExcel实现导入导出

news2024/11/23 3:39:51

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依赖导入

<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条都被成功导入到数据库表当中,并且数据都是正确的。

4、接下来实现导出

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 列名和数据都正确

5、总结

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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1370242.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

线性代数_同济第七版

contents 前言第1章 行列式1.1 二阶与三阶行列式1.1.1 二元线性方程组与二阶行列所式1.1.2 三阶行列式 1.2 全排列和对换1.2.1 排列及其逆序数1.2.2 对换 1.3 n 阶行列式的定义1.4 行列式的性质1.5 行列式按行&#xff08;列&#xff09;展开1.5.1 引理1.5.2 定理1.5.3 推论 * …

ULINK2仿真器安装使用之工程设置

一、 ULINK2仿真器 ULINK2是ARM公司最新推出的配套RealView MDK使用的仿真器&#xff0c;是ULink仿真器的升级版本。ULINK2不仅具有ULINK仿真器的所有功能&#xff0c;还增加了串行调试&#xff08;SWD&#xff09;支持&#xff0c;返回时钟支持和实时代理等功能。开发工程师通…

常用注解/代码解释(仅个人使用)

目录 第一章、代码解释①trim() 方法以及(Arrays.asList(str.split(reg)));②查询字典项②构建后端镜像shell命令解释 第二章、注解解释①PropertySource注解与Configurationproperties注解的区别 第三章、小知识①Linux系统中使用$符号表示变量 友情提醒: 先看文章目录&#…

强化学习求解TSP(二):Qlearning求解旅行商问题TSP(提供Python代码)

一、Qlearning简介 Q-learning是一种强化学习算法&#xff0c;用于解决基于奖励的决策问题。它是一种无模型的学习方法&#xff0c;通过与环境的交互来学习最优策略。Q-learning的核心思想是通过学习一个Q值函数来指导决策&#xff0c;该函数表示在给定状态下采取某个动作所获…

AI大模型引领未来智慧科研暨ChatGPT在地学、GIS、气象、农业、生态、环境应用

以ChatGPT、LLaMA、Gemini、DALLE、Midjourney、Stable Diffusion、星火大模型、文心一言、千问为代表AI大语言模型带来了新一波人工智能浪潮&#xff0c;可以面向科研选题、思维导图、数据清洗、统计分析、高级编程、代码调试、算法学习、论文检索、写作、翻译、润色、文献辅助…

办公文档,私人专用

一、安装Minio 1.1、创建文件夹&#xff0c;并在指定文件夹中下载minio文件 cd /opt mkdir minio cd minio touch minio.log wget https://dl.minio.io/server/minio/release/linux-amd64/minio1.2、赋予minio文件执行权限 chmod 777 minio1.3、启动minio ./minio server /…

SpiderFlow爬虫平台 前台RCE漏洞复现(CVE-2024-0195)

0x01 产品简介 SpiderFlow是新一代爬虫平台,以图形化方式定义爬虫流程,以流程图的方式定义爬虫,不写代码即可完成爬虫,是一个高度灵活可配置的爬虫平台。 0x02 漏洞概述 SpiderFlow爬虫平台src/main/java/org/spiderflow/controller/FunctionController.java文件的Functi…

三、POD详解

目录 一、Pod创建过程&#xff1a; 二、Pod的终止 三、pod配置详解 四、查看每种资源的可配置项 五、Pod状态 六、Pod调度 七、Pod探针 1、Pod 探针的检测方式&#xff1a; 一、Pod创建过程&#xff1a; 用户提交创建pod请求API Server处理用户请求&#xff0c;存储Pod…

【心得】SSRF攻击面利用个人笔记

SSRF的利用面 目录 1 任意文件读取 前提是知道要读取的文件名 2 探测内网资源 3 使用gopher协议扩展攻击面 4 php原生类进行ssrf 5 ssrf绕过 1 任意文件读取 前提是知道要读取的文件名 2 探测内网资源 127.0.0.1 mysql服务端监听了127.0.0.1这个地址&#xff0c;也就表示…

Linux 网络设置与基础服务

一 配置网络设置 主机名 hostname IP地址/netmask ifconfig &#xff1b; ip a 路由&#xff1a;默认网关 route -n DNS服务器 cat /etc/resolv.conf 网络连接状态 ss netstat 域名解析 ns…

前端炫酷动画特效分享(附在线预览)

分享7款非常有趣的前端特效源码 其中包含css动画特效、js原生特效、svg特效以及小游戏等 下面我会给出特效样式图或演示效果图 但你也可以点击在线预览查看源码的最终展示效果及下载源码资源 canvas鼠标粒子跟随动画 canvas鼠标粒子跟随动画 当鼠标移入背景区域时 粒子动画会…

Node.js和npm

目录 01_Node.js01.什么是 Node.js目标讲解小结 02.fs模块-读写文件目标讲解小结 03.path模块-路径处理目标讲解小结 04.案例-压缩前端html目标讲解小结 05.认识URL中的端口号目标讲解小结 06.http模块-创建Web服务目标讲解小结 07.案例-浏览时钟目标讲解小结 02_Node.js模块化…

解决vscode无法运行npm和node.js命令的问题

第一次安装npm和node.js想要在vscode中直接输入控制台命令会因为权限问题无法执行。 这里可以修改本机权限来解决。 搜索powershell并且以管理员权限运行 打开之后输入下面的命令即可 PS C:\Users\Administrator> Get-ExecutionPolicy Restricted PS C:\Users\Administra…

electron自定义窗口和右键菜单样式

前言 electron默认沿用系统UI&#xff0c;并没有提供很多接口供使用者定制样式&#xff0c;如果想要完全自定义的样式&#xff0c;目前我能想到的方案只能是通过前端自定义样式&#xff0c;然后通过进程通信来实现系统基础功能&#xff1a;最大/小化、关闭、拖动窗口等。 效果…

canvas绘制路径之 beginPath() 和 closePath()

查看专栏目录 canvas示例教程100专栏&#xff0c;提供canvas的基础知识&#xff0c;高级动画&#xff0c;相关应用扩展等信息。canvas作为html的一部分&#xff0c;是图像图标地图可视化的一个重要的基础&#xff0c;学好了canvas&#xff0c;在其他的一些应用上将会起到非常重…

权威mcc mnc 列表网址

MCC-MNC.net 链接: MCC-MNC.net 这个网站提供的mcc mnc 比下面itu文档中更全。 itu.int 2023年发布的mcc mnc分配信息&#xff1a; 链接: PDF T-SP-E.212B-2023 若想获取最新的可以参考如下截图查询&#xff1a;

linux开发板静态IP无法ping通外网

硬件平台&#xff1a;韦东山的6ull开发板 问题&#xff1a; 使用网线直连路由器&#xff0c;动态获取IP时能ping通外网&#xff1b; 改为静态IP时&#xff0c;能ping通局域网&#xff0c;但无法ping通外网。 改为静态IP&#xff1a;修改/etc/network/interfaces 测试&#…

论文阅读 Attention is all u need - transformer

文章目录 1 摘要1.1 核心 2 模型架构2.1 概览2.2 理解encoder-decoder架构2.2.1 对比seq2seq&#xff0c;RNN2.2.2 我的理解 3. Sublayer3.1 多头注意力 multi-head self-attention3.1.1 缩放点乘注意力 Scaled Dot-Product Attention3.1.2 QKV3.1.3 multi-head3.1.4 masked 3.…

EDA期末突击

。数模 1.1 进制转换 八位补码计算 1.2 化简函数 卡诺图 卡诺图另类的化简 1.3 逻辑图 看逻辑图 写表达式 列真值表&#xff0c;写出标准与或式 画逻辑图 ———————————————— 1.4 加法器 半加器 全加器 1.5 触发器 —————————————— …

(一)Spring Cloud 直击微服务作用、架构应用、hystrix降级

直击微服务作用 微服务架构: 遇到了什么问题? 将单体架构拆分成微服务架构后,如果保证多个服务(项目)正常运行? 哪个技术可以解决这个问题? 微服务技术 服务治理: 服务管理,维护服务与服务之间的关系 这个技术如何使用? netflix/网…