【日常需求】一次使用EasyExcel而引发的问题与思考~
文章目录
- 前言
- 如何利用EasyExcel解析Excel
- 1. 首先要定义一个对象
- 2. 创建监听器
- 3. 解析excel
- 完结撒花 ???
- 如何解决?
- 后话
前言
大家好啊,我是皮皮虾~,最近接的个需求中有个小功能是要上传用户id或email的excel,解析返回出正常的用户数和异常的用户数(简单来说就是能查到用户信息的数量和不能查到的数量)。
擦,我寻思这不得涉及到流的操作,这可是我的弱项啊~
当然来,正经人谁直接手写,当然要拥抱开源啦,这不就遇到了阿里的EasyExcel
如何利用EasyExcel解析Excel
1. 首先要定义一个对象
根据EasyExcel的思想,excel的每一行都认为是一个对象,每一列可以认为是一个字段
那么对应到Java中,我们就可以建一个实体类,来对应我们需要解析的Excel。
实习类中的字段注意要加上@ExcelProperty
注解
@Data
@AllArgsConstructor
@NoArgsConstructor
public class UserData {@ExcelProperty(index = 0)private Long uid;@ExcelProperty(index = 1)private String email;}
@ExcelProperty
注解,可以设置如下四个字段的值,一般情况下,我们需要设置 index 代表这个字段是对应的第几列(从0开始),或者设置 value 代表列名称,也就是通过列名称来匹配
**要注意的是,在官方文档中也提示了我们,不要同时使用index和value,如果excel没有设置标题或者标题重复可能导致解析不尽人意~ **
2. 创建监听器
创建一个监听器类,可以选择继承AnalysisEventListener
类或者实现ReadListener
接口
那么这两个有什么区别嘞?
其实区别不大,AnalysisEventListener
实现了ReadListener
的四个方法,主要的话还是在于对于表头数据的读取,通过重写invokeHead
方法,帮我们手动将表头数据转换了一下,这样如果我们需要读取表头数据的话,直接继承AnalysisEventListener
,实现invokeHeadMap
即可,不然如果是依然实现ReadListener
,我们还需要手动ConverterUtils.convertToStringMap
转换
@EqualsAndHashCode(callSuper = true)
@Slf4j
@Data
@AllArgsConstructor
public class UserDataListener extends AnalysisEventListener<UserData> {/*** uid集合*/private List<Long> uidList;/*** 邮箱集合*/private List<String> emailList;/*** 有效用户数量*/private Integer validUserNum;/*** 无效用户数量*/private Integer invalidUserNum;/*** 类型(0:uid,1:email)*/private Integer type;public UserDataListener(Integer type) {this.type = type;if (type.equals(0)) {uidList = new ArrayList<>();return;}emailList = new ArrayList<>();}@Overridepublic void invoke(UserData data, AnalysisContext context) {if (type.equals(0)) {uidList.add(data.getUid());return;}emailList.add(data.getEmail());}@Overridepublic void doAfterAllAnalysed(AnalysisContext context) {// 解析完成之后调用该方法 /*** rpc批量查询用户信息,通过type来区分是通过uidList查询还是emailList查询* ps:批量查询中,如果用户uid或者email不存在,最终返回的结果里则不包含该用户信息* 所以,rpc用户集合数量 <= uidList.size() or emailList.size()* 通过这个来计算validUserNum 和 invalidUserNum*/}@Overridepublic void onException(Exception exception, AnalysisContext context) {throw new RuntimeException("解析user excel异常", exception);}}
3. 解析excel
获取前端传过来的excel文件和上传类型,进行基本的参数校验之后,进行excel的解析
要注意的是监听器不能被Spring管理,每次都要去new一个新的对象
@Override
public UserUploadVO uploadFile(MultipartFile file, Integer type) throws Exception {if (file == null || type == null) {throw new RuntimeException("Param error");}UserUploadVO userUploadVO = new UserUploadVO();String fileName = file.getOriginalFilename();if (StringUtils.isEmpty(fileName)) {return userUploadVO;}String fileXlsx = fileName.substring(fileName.length() - 5);String fileXls = fileName.substring(fileName.length() - 4);if (!".xlsx".equals(fileXlsx) && !".xls".equals(fileXls)) {return userUploadVO;}UserDataListener userDataListener = new UserDataListener(type);// 解析excelEasyExcel.read(file.getInputStream(), UserData.class, userDataListener).sheet().doRead();// 设置有效用户数和无效用户数userUploadVO.setInvalidUserNum(userDataListener.getInvalidUserNum());userUploadVO.setValidUserNum(userDataListener.getValidUserNum());return userUploadVO;
}
由于计算有效用户数和无效用户数是口述了下逻辑,这边就不给小伙伴们去展示结果啦,有兴趣的小伙伴们可以自己试试
完结撒花 ???
本来写到这,皮皮虾已经自测通过了,觉得没啥问题了,但我突然又去嘴贱的问了下产品姐姐
皮皮虾:产品姐姐,那上传的时候,如果是传uid的excel都从第一列第二行开始,传email的excel都从第二列第二行开始可以不?
产品姐姐:为啥要这样嘞?都从第一列第二行开始不好嘛,我觉得统一一点比较好,不然上传的时候有问题,大家都以为是bug。
前面已经跟大家提过了,EasyExcel每一行都认为是一个对象,我们在字段上添加@ExcelProperty(index = 0)
注解时,已经表明了这个字段是第几列的数据…,现在都搞到第一列,本质上还一个是String
一个是Long
不过想想,人家产品说的也有道理,于是我礼貌的回复了下:好的啊~
如何解决?
看者眼前的聊天框,我陷入的沉思…,艹,大不了我写两套代码,能实现需求就行
一段狂敲代码过后,原本的一个实体类一个监听器,变成了两个实体类两个监听器,解析exel逻辑里也充满了if-else…
测试过后也没发现有啥问题,十分的nice
虽然功能实现了,但是看着眼前屎山般的代码,我恨不得抽自己两巴掌,这写的什么玩意
【日常需求】一次使用EasyExcel而引发的问题与思考~相关推荐
- Cobot专长:了解您的日常需求
专长:了解您的日常需求 合作机器人和末端执行器联手提供Cobot价格合理的灵活解决方案.尽管机器人技术引领着自动化的快速增长,但我们将协作机器人视为机器人技术的民主化.它们消除了机器人通常需要的成本和 ...
- linux 服务器 日常命令 日常需求
linux 服务器 日常命令 日常需求 文件管理 文本筛选-grep 截取字段-awk 对文件内容修改-sed 查找 下载文件 Http请求 上传 下载 压缩 解压 排序去重-sort.uniq 数值 ...
- 一次洗脚引发的线程池思考
一次洗脚引发的线程池思考,文末有惊喜 上周末和好朋友大凯子约好周末去洗脚放松一下,毕竟忙了一周了,又加了几天班,身心疲惫,好的身体是革命的本钱,男人可得好好爱惜自己的身体,不能倒在革命的道路上,于是第 ...
- C/C++ 由int (*p)[5]与int *p[5]引发的学习与思考
由int (*p)[5]与int *p[5]引发的学习与思考 最近在大一上复习指针这部分时,有个C指针的特例一直困扰着我.我查阅了许多课本,也看了CSDN上许多大佬的理解.自我感觉受益匪浅,现记录下自 ...
- 轩逸酷我音乐显示服务器错误,第14代轩逸车机系统体验:基本满足日常需求 随车流量模糊不清...
[资讯-牛车网] 上一篇,牛车实验室为大家介绍了第14代轩逸搭载的日产智联系统.整体来说,这套智联系统的功能较为单一,用户体验亟待提升.智联系统略显鸡肋,那么与车主交流更为密切的车机系统使用体验如何呢 ...
- 史上最简单的springcloud微服务入门实例,满足企业日常需求,开箱即用,工资翻倍不是梦...
在传统的IT行业软件大多都是各种独立系统的堆砌,这些系统的问题总结来说就是扩展性差,可靠性不高,维护成本高.到后面引入了SOA服务化,但是,由于 SOA 早期均使用了总线模式,这种总线模式是与某种技术 ...
- NTA告警引发的dll劫持思考(溯源)
目录 溯源 DLL DLL Hijacking Vulnerability(DLL劫持漏洞) DLL劫持攻击 转发式劫持 DLL劫持防御 某天在客户局点巡检时,NTA设备发现了CS的告警:定位了被入侵 ...
- C++11中的时间库std::chrono(引发关于时间的思考)
文章目录 前言 chrono 的概况 chrono 的核心内容 duration clock system_clock steady_clock time point 关于时间的思考 时间函数思考 总 ...
- 公理设计:由奇怪海战引发的软件设计思考
前几天看到了一个博客,推荐了<公理设计>一书,还有其相关的文档以及视频.简单了解了一下,增深了一些对软件设计的理解,特此也推荐给大家. 公理设计理论将设计建立在科学公理.定理和推论的基础上 ...
最新文章
- J. Cheminform. | DrugEx v2:多重药理学中基于pareto的多目标强化学习的药物分子从头设计...
- 测试页打印失败0x0000045a_激光打印机就该选这样的,联想领像L100DW评测
- java excel 复杂表头_中国式复杂报表开发教程(4)—类Excel复杂表头报表
- 模板设计模式,简单Java代码实现
- linux deb文件安装_如何在 Ubuntu 上安装 VirtualBox | Linux 中国
- 为MFC中的ListBox添加水平滚动条
- C# 接受MQTT服务器推送的消息
- 重读经典:《Momentum Contrast for Unsupervised Visual Representation Learning》
- mysql数据库连接锁住_锁mysql方法
- 不可求的电脑上必备软件,你也许听过
- WAMP显示错误“MSVCR100.dll”缺少安装时
- linux HZ 值_Linux操作系统中进程的操作命令(ps,kill,keep)
- 【CDOJ1330】柱爷与远古法阵(高斯消元+卡精度+概率dp?)
- vue 日期多选插件
- Error querying database. Cause: java.sql.SQLException: ORA-01008: 并非所有变量都已绑定
- JSP——编写一个简单的JSP页面,显示英文字母表
- 这么黄的教程,我看了2小时就关了!
- 柴夥說算法(4)--再說樹
- 前端埋点数据收集及上报方案
- STM32 串口 FIFO