spring boot-操作excel(EasyExcel 快速开始)/ spring boot接受文件参数 File

文章目录

  • [一、spring boot 操作excel](#一、spring boot 操作excel)
    • [1. 技术选型](#1. 技术选型)
      • [1.1 EasyExcel](#1.1 EasyExcel)
      • [1.2 POI](#1.2 POI)
  • 二、EasyExcel使用
    • [0. 工作中使用总结](#0. 工作中使用总结)
    • [1. maven 引入](#1. maven 引入)
    • [2. demo1:excel写入文件](#2. demo1:excel写入文件)
    • [3. demo2:SpringBoot项目中集成EasyExcel实现Excel文件的下载](#3. demo2:SpringBoot项目中集成EasyExcel实现Excel文件的下载)
    • [4. demo3:SpringBoot项目中集成EasyExcel实现Excel文件导入(同步处理数据)](#4. demo3:SpringBoot项目中集成EasyExcel实现Excel文件导入(同步处理数据))
      • [4.1 AnalysisEventListener](#4.1 AnalysisEventListener)
  • 三、工作常用参考
    • [1. easyexcel 上传返回结果给前端(返回成功/失败数量及原因)](#1. easyexcel 上传返回结果给前端(返回成功/失败数量及原因))
    • [2. easyexcel 导入数据校验](#2. easyexcel 导入数据校验)
  • 四、参考

一、spring boot 操作excel

1. 技术选型

java本身并不支持读取excel,所有读取excel需要借助一些框架。目前有几种方式:

  1. Apache POI
  2. easyexcel

POI提供的对Excel操作不仅消耗内存而且解压时完全在内存中完成,内存消耗非常大。

  • easyExcel的确比poi方便,但是它的读需要编写监听器
  • 建议大数据用easyExcel,因为大数据时poi对于内存消耗非常大
  • 由于apache poi和jxl,excelPOI都有一个严重的问题,就是非常消耗内存,特别处理数据量多时,速度慢并且时有异常发生,所以改用由阿里研发的easyExcel更可靠一些,它的官方建议对于1000行以内的采用原来poi的写法一次读写,但于1000行以上的数据,有用了一行行进行解析的方案,这样避免了内存的溢出。
  • EasyExcel扩展功能很多,且Api式调用真的轻松很多

1.1 EasyExcel

官方网站: https://yuque.com/easyexcel

https://github.com/alibaba/easyexcel

EasyExcel是阿里巴巴开源的一个excel处理框架,以使用简单、节省内存著称。

EasyExcel是一个基于Java的简单、省内存的读写Excel的开源项目。在尽可能节约内存的情况下支持读写百M的Excel。

EasyExcel能减少内存占用的原因是它没有将文件一次性加载到内存中,而是从磁盘上一行行读取数据,逐个解析。

EasylExcel的特点:

1、poi和jxl非常的消耗内存,并发上来后会OOM或是JVM频繁的full gc。

2、EasylExcel对poi进行了封装,使用简单,节省内存。

3、EasyExcel没有把文件数据一次性全部加载到内存中,而是从磁盘一行一行读取数据,逐个解析,并将解析结果以观察者的模式通知处理(AnalysisEventListener)。

1.2 POI

POI是Apache提供的开源代码库,这个代码库用来提供Java客户端对Microsoft Office格式文件的读写操作。

POI为"Poor Obfuscation Implementation"的首字母缩写,意为"简洁版的模糊实现"。

POI有五种结构

HSSF------提供读写Microsoft Excel(2003)格式档案功能

XSSF------提供读写Microsoft Excel OOXML(2007-今)格式档案的功能

HWPF------提供读写Microsoft Word格式档案的功能

HSLF------提供读写Microsoft PPT格式档案功能

HDGF------提供读写Microsoft Visio格式档案的功能

二、EasyExcel使用

0. 工作中使用总结

  • 目前读取excel文件不再需要指定ExcelTypeEnum,即excel的版本,会自动处理
  • 之前创建ExcelReader都是自己new,现在是通过EasyExcelFactory创建,更加简单和具备通用性。
  • 之前每解析一行的回调的invoke()方法,通用对象Object是list集合,目前是HashMap集合。

1. maven 引入

repo仓库搜索 关键字 EasyExcel ,使用最新版本。

java 复制代码
<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>easyexcel</artifactId>
    <version>2.1.3</version>
</dependency>

2. demo1:excel写入文件

java 复制代码
@HeadRowHeight(20)	// 表头行高
@ColumnWidth(15)		// 表头行宽
@Data
public class DemoData {
    @ExcelProperty("字符串标题")
    private String string;
    @ExcelProperty("日期标题")
    private Date date;
    @ExcelProperty("数字标题")
    private Double doubleData;
    /**
     * 忽略这个字段
     */
    @ExcelIgnore
    private String ignore;
}
java 复制代码
public class ExcelServiceTest {

    /**
     * 最简单的写
     * <p>1. 创建excel对应的实体对象 参照{@link DemoData}
     * <p>2. 直接写即可
     */
    @Test
    public void simpleWrite1() {
        // 写法1
        String fileName = "simpleWrite" + System.currentTimeMillis() + ".xlsx";
        // 这里 需要指定写用哪个class去写,然后写到第一个sheet,名字为模板 然后文件流会自动关闭
        // 如果这里想使用03 则 传入excelType参数即可
        EasyExcel.write(fileName, DemoData.class).sheet("模板").doWrite(data());
    }

    @Test
    public void simpleWrite2(){
        // 写法2
        String fileName = "simpleWrite" + System.currentTimeMillis() + ".xlsx";
        // 这里 需要指定写用哪个class去写
        ExcelWriter excelWriter = null;
        try {
            excelWriter = EasyExcel.write(fileName, DemoData.class).build();
            WriteSheet writeSheet = EasyExcel.writerSheet("模板").build();
            excelWriter.write(data(), writeSheet);
        } finally {
            // 千万别忘记finish 会帮忙关闭流
            if (excelWriter != null) {
                excelWriter.finish();
            }
        }
    }

    private List<DemoData> data() {
        List<DemoData> list = new ArrayList<DemoData>();
        for (int i = 0; i < 10; i++) {
            DemoData data = new DemoData();
            data.setString("字符串" + i);
            data.setDate(new Date());
            data.setDoubleData(0.56);
            list.add(data);
        }
        return list;
    }

}

3. demo2:SpringBoot项目中集成EasyExcel实现Excel文件的下载

SpringBoot项目中集成EasyExcel实现Excel文件的下载

参考URL: https://blog.csdn.net/riemann_/article/details/103648431

如下:demo测试通过, 利用 response.getOutputStream() 、HttpServletResponse response 来设置响应头等信息。

java 复制代码
    @RequestMapping(value = "/xxx/getExcel", method = RequestMethod.GET)
    public void getExcel(HttpServletResponse response) throws IOException {

        //配置文件名
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd-HH:mm:ss");
        String datetime = sdf.format(new Date());
        String fileName = URLEncoder.encode("下载excel", "UTF-8") + datetime;

        //响应内容格式
        response.setContentType("application/vnd.ms-excel");
        response.setCharacterEncoding("utf-8");
        response.setHeader("Content-disposition", "attachment;filename=" + fileName + ".xlsx");
        
        List<UserVO> list = excelService.getUserVOData();
        // 这里 需要指定写用哪个class去写,然后写到第一个sheet,名字为模板 然后文件流会自动关闭
        // 如果这里想使用03 则 传入excelType参数即可
        EasyExcel.write(response.getOutputStream(), UserCheckData.class).sheet("下载excel").doWrite(list);

    }

UserCheckData.class 是自定义的excel对应的java类;其中的

@ExcelProperty注解中的value就是表头的信息,index是在第几列,没有加注解的不会导出。

java 复制代码
@HeadRowHeight(20)	// 表头行高
@ColumnWidth(15)		// 表头行宽
@Data
public class SiUserCheckData{

    /**
     * 用户名
     */
    @ExcelProperty(value = "用户名", index = 0)
    private String username;

    /**
     * 手机号
     */
    @ExcelProperty(value = "手机号", index = 0)
    private String mobile;
}

如上demo,经过测试,注意点如下:

  • response 来设置响应头等信息,记得要放在EasyExcel.write 写流之前。
  • controller方法写成void即可。

response的三个属性:编码、类型、头文件

流写出时,关键是配置response的三个属性:编码、类型、头文件

1、ContentType:传输文件类型

application/octet-stream------------------自动匹配文件类型

application/force-download--------------强制下载

text/pain---------------------------------------文本文件

application/vnd.ms-excel-----------------excel文件

2、CharacterEncoding:编码采用通用的UTF-8

3、Header:setHeader(name,value),有两个参数


示例:

java 复制代码
response.setContentType("application/vnd.ms-excel");

response.setCharacterEncoding("UTF-8");

response.setHeader("Content-Disposition","attachment;filename=problems"+AMDateUtil.date2String(new Date(),"yyyyMMdd")+".xlsx");

4. demo3:SpringBoot项目中集成EasyExcel实现Excel文件导入(同步处理数据)

SpringBoot项目中集成EasyExcel实现Excel文件上传至MySQL

参考URL: https://blog.csdn.net/riemann_/article/details/103639254

使用easyExcel导入大批量数据

参考URL: https://blog.csdn.net/qq_36109477/article/details/104909535

推荐\]springboot整合阿里easyexcel2.x实现海量数据excel导入导出demo 参考URL: https://www.cnblogs.com/zhengwj-joker/p/12808979.html 整体思路: 1. 引入easyExcel maven。 2. 定义导入导出exel字段对应的实体类。(使用easyExcel相关注解) 3. 自定义 上传Excel的监听类 实现 AnalysisEventListener\<你自己定义的excel模型类\>。 核心就是这个监听器类,实现相关方法。 经过测试: 监听器这个类不能够被Spring管理,每次使用单独的new出来。 ```java // 该类无法交给spring管理 public class ConfigFilterListener extends AnalysisEventListener { private static final Logger logger = LoggerFactory.getLogger(ConfigFilterListener.class); private static final int BATCH_COUNT = 10000; List list = new ArrayList<>(); private ConfigFilterDao configFilterDao; /** * 如果使用了spring,请使用这个构造方法。每次创建Listener的时候需要把spring管理的类传进来 */ public ConfigFilterListener(ConfigFilterDao configFilterDao){ this.configFilterDao = configFilterDao; } /** * 这个每一条数据解析都会来调用 * * @param configFilter * one row value. Is is same as {@link AnalysisContext#readRowHolder()} * @param analysisContext */ @Override public void invoke(ConfigFilterImport configFilter, AnalysisContext analysisContext) { list.add(configFilter); // 达到BATCH_COUNT了,需要去存储一次数据库,防止数据几万条数据在内存,容易OOM if (list.size() >= BATCH_COUNT) { saveData(); // 存储完成清理 list list.clear(); } } @Override public void doAfterAllAnalysed(AnalysisContext analysisContext) { // 这里也要保存数据,确保最后遗留的数据也存储到数据库 saveData(); logger.info("所有数据解析完成!"); } /** * 加上存储数据库 */ private void saveData() { logger.info("{}条数据,开始存储数据库!", list.size()); configFilterDao.save(list); logger.info("存储数据库成功!"); } } ``` 参考原博主URL(`https://www.cnblogs.com/zhengwj-joker/p/12808979.html`),即可。 #### 4.1 AnalysisEventListener 上文中,自定义 上传Excel的监听类 实现 AnalysisEventListener\<你自己定义的excel模型类\>, 其中, invoke() 和 doAfterAllAnalysed() 是必须实现的方法。 在 invoke() 中,我们将数据封装到 list 中,再在控制器中,通过 getter() 方法获取数据,这样我们就可以获取到 easyexcel 帮我们解析好的数据,再将数据进行类型转化,这样,我们就可以对数据进行写入操作。 注意: * 每解析一行会回调invoke()方法。 * 整个excel解析结束会执行doAfterAllAnalysed()方法 > 经过测试,自定义监听类 实现 AnalysisEventListener不能被spring管理。即使你加了 @Component注解,发现里面 @Autowired 注入不了spring 的bean! 那么,我们要使用spring bean应该怎么做呢? 思路:监听器对象 可以在创建的时候把dao当做参数传进去。 我们自定义监听器类的构造体传入,需要用到bean,如一些Dao ```java /** * * 不要使用自动装配 * 将dao当参数传进来 */ public DemoDataListener(TeacherDao teacherDao) { this.teacherDao = teacherDao; } ``` ```java /** * 添加数据库用到的dao */ @Autowired private TeacherDao teacherDao; /** * 最简单的读 */ @Test public void simpleRead() { String fileName = "/Users/lubingyang/Desktop/hhhh.xlsx"; // 这里 需要指定读用哪个class去读,然后读取第一个sheet 文件流会自动关闭 /** * 参数1 要读取的文件 * 参数2 要读取的数据对应的实体类类对象 * 参数3 监听器对象 可以在创建的时候把dao当做参数传进去 */ EasyExcel.read(fileName, Teacher.class, new DemoDataListener(teacherDao)).sheet().doRead(); } ``` ## 三、工作常用参考 ### 1. easyexcel 上传返回结果给前端(返回成功/失败数量及原因) 基于EasyExcel的读取exl并返回成功/失败数量及原因,并将导入失败exl的导出到系统路径中 参考URL: https://blog.csdn.net/qq_37361535/article/details/105687708 https://blog.csdn.net/weixin_42059737/article/details/103891013 参考URL: https://blog.csdn.net/weixin_42059737/article/details/103891013 整体思路: 自定义类bean,spring管理,专门处理统计哪些入库成功,哪些失败,在自定义excel监听器构造函数中传入。 controller层如何返回给界面,哪些成功或失败呢? > 其中controller层需要返回给前端的数据,可以利用该思想。在监听器构造函数添加需要返回的实例。监听器里面做相关赋值,controller层直接返回即可。 controller层,demo如下: ```java @ResponseBody @RequestMapping(value = "orderImport", method = RequestMethod.POST, produces = Constant.CONTENT_TYPE_UTF8) public RestResponse orderImport(HttpServletRequest request, @RequestParam(value = "file") MultipartFile file) throws Exception { UserVO userVo = this.getCurrentUser(request); // 初始化ajax返回对象 默认是操作成功 RestResponse build = RestResponse.build(); EasyExcel.read(file.getInputStream(), new NoModleDataListener(orderService, userVo, build)).sheet().doRead(); // 直接返回 如果错误这个对象的值已被改变 如果没有错误值没有被改变 返回的是默认成功的对象 return build; // return orderService.importOrder(userVo, file); } ``` 建议直接参考原文。 ### 2. easyexcel 导入数据校验 easyExcel+validation+正则实现excel导入校验 参考URL: https://www.yuque.com/oushidazhutou/lwb5fl/mwymlq ## 四、参考 EasyExcel2.0 实现模板下载、导入和导出功能 参考URL: https://liuyanzhao.com/10060.html EasyExcel操作API与示例 参考URL: https://www.it610.com/article/1296387796709220352.htm EasyExcel读取文件-同步处理数据 参考URL: https://www.cnblogs.com/ngrzr/p/11982697.html SpringBoot图文教程14---阿里开源EasyExcel「为百万数据读写设计」 参考URL: https://my.oschina.net/u/3555122/blog/4355952 惊了!如何通过阿里 EasyExcel 7 行代码, 优雅地实现 Excel 文件导出功能? 参考URL: https://blog.csdn.net/wutian842929/article/details/106994662/ easyExcel+validation+正则实现excel导入校验 参考URL: https://www.yuque.com/oushidazhutou/lwb5fl/mwymlq

相关推荐
IT_陈寒4 分钟前
Redis 性能翻倍的 5 个隐藏技巧,99% 的开发者都不知道第3点!
前端·人工智能·后端
JaguarJack4 分钟前
PHP 桌面端框架NativePHP for Desktop v2 发布!
后端·php·laravel
番茄Salad5 分钟前
自定义Spring Boot Starter项目并且在其他项目中通过pom引入使用
java·spring boot
RECRUITGUY15 分钟前
Excel中将毫秒时间戳转换为标准时间格式
excel
自由的疯27 分钟前
Java 怎么学习Kubernetes
java·后端·架构
自由的疯27 分钟前
Java kubernetes
java·后端·架构
SunkingYang2 小时前
详细介绍C++中捕获异常类型的方式有哪些,分别用于哪些情形,哪些异常捕获可用于通过OLE操作excel异常
c++·excel·mfc·异常捕获·comerror
QX_hao7 小时前
【Go】--map和struct数据类型
开发语言·后端·golang
MC丶科7 小时前
【SpringBoot 快速上手实战系列】5 分钟用 Spring Boot 搭建一个用户管理系统(含前后端分离)!新手也能一次跑通!
java·vue.js·spring boot·后端
G探险者8 小时前
为何一个系统上线要经过N轮测试?带你看懂企业级发布体系
后端