当前位置: 首页 > news >正文

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

文章目录

  • 一、spring boot 操作excel
    • 1. 技术选型
      • 1.1 EasyExcel
      • 1.2 POI
  • 二、EasyExcel使用
    • 0. 工作中使用总结
    • 1. maven 引入
    • 2. demo1:excel写入文件
    • 3. demo2:SpringBoot项目中集成EasyExcel实现Excel文件的下载
      • response的三个属性:编码、类型、头文件
    • 4. demo3:SpringBoot项目中集成EasyExcel实现Excel文件导入(同步处理数据)
      • 4.1 AnalysisEventListener
  • 三、工作常用参考
    • 1. 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 ,使用最新版本。

<dependency><groupId>com.alibaba</groupId><artifactId>easyexcel</artifactId><version>2.1.3</version>
</dependency>

2. demo1:excel写入文件

@HeadRowHeight(20)	// 表头行高
@ColumnWidth(15)		// 表头行宽
@Data
public class DemoData {@ExcelProperty("字符串标题")private String string;@ExcelProperty("日期标题")private Date date;@ExcelProperty("数字标题")private Double doubleData;/*** 忽略这个字段*/@ExcelIgnoreprivate String ignore;
}
public class ExcelServiceTest {/*** 最简单的写* <p>1. 创建excel对应的实体对象 参照{@link DemoData}* <p>2. 直接写即可*/@Testpublic void simpleWrite1() {// 写法1String fileName = "simpleWrite" + System.currentTimeMillis() + ".xlsx";// 这里 需要指定写用哪个class去写,然后写到第一个sheet,名字为模板 然后文件流会自动关闭// 如果这里想使用03 则 传入excelType参数即可EasyExcel.write(fileName, DemoData.class).sheet("模板").doWrite(data());}@Testpublic void simpleWrite2(){// 写法2String 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 来设置响应头等信息。

    @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是在第几列,没有加注解的不会导出。

@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),有两个参数


示例:

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出来。
// 该类无法交给spring管理
public class ConfigFilterListener  extends AnalysisEventListener<ConfigFilterImport> {private static final Logger logger = LoggerFactory.getLogger(ConfigFilterListener.class);private static final int BATCH_COUNT = 10000;List<ConfigFilterImport> 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*/@Overridepublic void invoke(ConfigFilterImport configFilter, AnalysisContext analysisContext) {list.add(configFilter);// 达到BATCH_COUNT了,需要去存储一次数据库,防止数据几万条数据在内存,容易OOMif (list.size() >= BATCH_COUNT) {saveData();// 存储完成清理 listlist.clear();}}@Overridepublic 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

    /**** 不要使用自动装配* 将dao当参数传进来*/public DemoDataListener(TeacherDao teacherDao) {this.teacherDao = teacherDao;}
/*** 添加数据库用到的dao*/@Autowiredprivate TeacherDao teacherDao;/*** 最简单的读*/@Testpublic 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如下:

	@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

相关文章:

  • 如何在Windows系统搭建Emby影音平台并实现远程访问本地文件【内网穿透】
  • 二进制安全找实习记录
  • unity内存优化之AB包篇(微信小游戏)
  • 动手学习深度学习之环境配置
  • STM32中MicroLIB的关闭为什么会导致卡死----解析
  • 【数据结构】堆
  • zookeeper快速入门二:zookeeper基本概念
  • 145 Linux 网络编程1 ,协议,C/S B/S ,OSI 7层模型,TCP/IP 4层模型,
  • 2.3 物理层设备
  • 开发K8S Operator
  • [Django 0-1] Core.Checks 模块
  • 传统电力运维企业的数字化转型案例
  • 数据结构的概念大合集03(栈)
  • 使用Docker搭建Jellyfin
  • 阿里提前批(阿里云)一面30min
  • [原]深入对比数据科学工具箱:Python和R 非结构化数据的结构化
  • Android 控件背景颜色处理
  • input实现文字超出省略号功能
  • Java多线程(4):使用线程池执行定时任务
  • 初探 Vue 生命周期和钩子函数
  • 七牛云 DV OV EV SSL 证书上线,限时折扣低至 6.75 折!
  • 腾讯优测优分享 | 你是否体验过Android手机插入耳机后仍外放的尴尬?
  • 学习HTTP相关知识笔记
  • C# - 为值类型重定义相等性
  • ​ArcGIS Pro 如何批量删除字段
  • # 达梦数据库知识点
  • #{}和${}的区别?
  • #stm32驱动外设模块总结w5500模块
  • (3)(3.5) 遥测无线电区域条例
  • (33)STM32——485实验笔记
  • (6)STL算法之转换
  • (八十八)VFL语言初步 - 实现布局
  • (附源码)apringboot计算机专业大学生就业指南 毕业设计061355
  • (四)c52学习之旅-流水LED灯
  • (小白学Java)Java简介和基本配置
  • (转)es进行聚合操作时提示Fielddata is disabled on text fields by default
  • (转)关于pipe()的详细解析
  • (转)可以带来幸福的一本书
  • .MyFile@waifu.club.wis.mkp勒索病毒数据怎么处理|数据解密恢复
  • .NET CORE 3.1 集成JWT鉴权和授权2
  • .net core使用ef 6
  • .net 生成二级域名
  • .NET(C#) Internals: as a developer, .net framework in my eyes
  • [ vulhub漏洞复现篇 ] JBOSS AS 5.x/6.x反序列化远程代码执行漏洞CVE-2017-12149
  • [ 蓝桥杯Web真题 ]-布局切换
  • [20150707]外部表与rowid.txt
  • [20190401]关于semtimedop函数调用.txt
  • [AIGC] MySQL存储引擎详解
  • [bzoj1324]Exca王者之剑_最小割
  • [HackMyVM]靶场 VivifyTech
  • [IE9] IE9 RC版下载链接
  • [LeetCode系列]子集枚举问题[无重复元素]
  • [LOJ161] 仙人掌计数
  • [oeasy]python0004_游乐场_和python一起玩耍_python解释器_数学运算
  • [P4V]Perforce(P4V)使用教程