码农知识堂 - 1000bd
  •   Python
  •   PHP
  •   JS/TS
  •   JAVA
  •   C/C++
  •   C#
  •   GO
  •   Kotlin
  •   Swift
  • 【二十四】springboot使用EasyExcel和线程池实现多线程导入Excel数据


      springboot篇章整体栏目: 


    【一】springboot整合swagger(超详细

    【二】springboot整合swagger(自定义)(超详细)

    【三】springboot整合token(超详细)

    【四】springboot整合mybatis-plus(超详细)(上)

    【五】springboot整合mybatis-plus(超详细)(下)

    【六】springboot整合自定义全局异常处理

    【七】springboot整合redis(超详细)

    【八】springboot整合AOP实现日志操作(超详细)

    【九】springboot整合定时任务(超详细)

    【十】springboot整合redis实现启动服务即将热点数据保存在全局以及redis(超详细)

    【十一】springboot整合quartz实现定时任务优化(超详细)

    【十二】springboot整合线程池解决高并发(超详细,保你理解)

    【十三】springboot整合异步调用并获取返回值(超详细)

    【十四】springboot整合WebService(超详细)

    【十五】springboot整合WebService(关于传参数)(超详细)

    【十六】springboot整合WebSocket(超详细)

    【十七】springboot整合WebSocket实现聊天室(超详细)

    【十八】springboot实现自定义全局异常处理

    【十九】springboot整合ElasticSearch实战(万字篇)

    【二十】springboot整合过滤器实战

    【二十一】springboot整合拦截器实战并对比过滤器

    【二十二】springboot整合activiti7(1) 实战演示篇

    【二十三】springboot整合spring事务详解以及实战

    【二十四】springboot使用EasyExcel和线程池实现多线程导入Excel数据


            在公司开发时,遇到一个很常见的导入功能的需求,需要导入Excel文件,由此想到了阿里巴巴的EasyExcel这个方便的工具,当客户给我说需要支持大数据量导入时,我想到了使用线程池来多线程处理导入数据库这个操作。由此本章记录一下这次操作。

            首先,整体的大概流程差不多是这个样子:

    ​

    效果:

    ​

    ​

    ​


            真实项目上是公司封装的RPC框架,这次demo直接使用的前面的整合mybatis-plus的demo来写的。

            首先看下目录结构:

    ​

            图片中框选部分就是本章需要修改到的或者新创建的文件,后面一一解读,下面的描述可以对标这个图片中的类名。

            然后介绍下本章需要做的准备工作:

    • 数据库表
    • 修改application配置文件,修改tomcat的最大文件上传限制(否则excel文件太大,上传会报错)
    • 开启mybatis-plus的批量插入功能,mybatis-plus默认只有insert这个单条插入功能(若自己的项目不使用这个,则不需要,这只是我的demo上没有批量插入方法)
    • 创建excel多线程导入接口所需的各个类

    目录

    一、准备数据库和Excel文件

    二、引入所需依赖

    三、修改配置文件,修改文件大小默认限制

    四、开启mybatis-plus的批量保存功能

    五、创建所需工具类

    六、创建业务各层代码

    七、创建easyExcel事件监听器

    八、创建自定义线程类

    九、测试单线程和多线程处理的效率


    一、准备数据库和Excel文件

    1. CREATE TABLE `deadman` (
    2. `uid` varchar(255) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL COMMENT '主键',
    3. `idCard` varchar(255) CHARACTER SET utf8 COLLATE utf8_bin DEFAULT NULL COMMENT '身份证号',
    4. `userName` varchar(255) CHARACTER SET utf8 COLLATE utf8_bin DEFAULT NULL COMMENT '死者姓名',
    5. `sex` varchar(255) CHARACTER SET utf8 COLLATE utf8_bin DEFAULT NULL COMMENT '死者性别',
    6. `age` varchar(255) CHARACTER SET utf8 COLLATE utf8_bin DEFAULT NULL COMMENT '死者年龄',
    7. `reason` varchar(255) CHARACTER SET utf8 COLLATE utf8_bin DEFAULT NULL COMMENT '死因',
    8. `house` varchar(255) CHARACTER SET utf8 COLLATE utf8_bin DEFAULT NULL COMMENT '安排地狱层数',
    9. PRIMARY KEY (`uid`)
    10. ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3 COLLATE=utf8_bin;

    ​

    ​


    二、引入所需依赖

            主要是导入easyExcel所涉及的依赖,如下:

    ​


    三、修改配置文件,修改文件大小默认限制

            这个必须修改,不然后面接口都进不去,默认tomcat服务器是限制了上传文件的大小的。

    spring:
      servlet:
        multipart:
          max-file-size: 100MB
          max-request-size: 100MB
    server:
      tomcat:
        max-swallow-size: 100MB 

    四、开启mybatis-plus的批量保存功能

            这次demo整合的rpc框架是Mybatis-plus,所以找了一个方法去实现批量保存,如下:

    1、新建一个SpiceSqlInjector类

    ​

    PS:注意框选部分类名。

    2、创建SpiceBaseMapper接口类

    ​

    PS:本来是业务的接口层去继承BaseMapper,此处又它去继承BaseMapper,然后加如上图这个方法,注意名称必须是这个否则后面调用该方法会报错。

    3、创建业务所需的Mapper层

    ​

    继承刚才自定义的接口类。

    由此就可以通过注入DeadManMapper调用上面的方法实现批量插入了。

    如下:

    ​


    五、创建所需工具类

            在通过EasyExcel导入时,会涉及到一些数据类型不满足入参之类的,本次demo涉及到如下工具类。

    1、MultipartFileToFileUtils

            将传入的MultipartFile类型转为File类型,Controller接收到的是MultipartFile类型,EasyExcel.read方法所需要的是File类型。

    ​

    2、SpringJobBeanFactory

            在监听器类注入mappe时会报空指针,使用如下工具类继承ApplicationContextAware,获取bean对象。

    ​


    六、创建业务各层代码

    1、controller层

    ​

    2、映射数据库的实体类

    ​

            关于mybatis-plus相关的注解可以去看看前面的文章。 

    3、easyExcel的实体类

    ​

            index指的是excel表上面的行编号,例如

    ​

    4、service层

    ​

    5、service的实现类层

    ​

            上面的方法是多线程处理的事件监听器,下面的是单线程的事件监听器,后面针对两种方式都做一下对比。 


    七、创建easyExcel事件监听器

    1、单线程的事件监听器

    ​

            解析:该监听器继承自AnalysisEventListener类,泛型指定为上面easyExcel指定的实体类对象类。重写该类的两个方法:invoke和doAfterAllAnalysed。 

    invoke():该方法会从excel表的第二行开始读取数据。

    doAfterAllAnalysed():当invoke将excel的数据全部解析完后,会执行该方法,所以在该类进行数据的入库即可。

            此时,单线程的导入已经完成,我们最后再对比测试两种监听器的效率,现在创建多线程事件监听器。 

    2、多线程的事件监听器

    ​

            解析:同样是重写上面说的那两个方法。invoke方法的处理不变,修改doAfterAllAnalysed方法的处理,在该方法通过创建线程池的方法,将创建的线程任务提交到线程池,让线程池进行多线程任务的执行,从而实现多线程执行导入操作。

    流程:创建线程池——》计算每个线程需要处理的数据——》创建CountDownLatch对象(保证最后每个线程会回到主线程)——》循环线程数量并提交线程任务到线程池——》执行CountDownLatch对象的await方法,让当前线程处于等待状态,等待CountDownLatch减少为1后会唤醒当前线程——》每个线程处理自己的数据并在处理完后执行CountDownLatch对象的countDown方法,让CountDownLatch对象的值减一——》当CountDownLatch的值为0时(说明线程池类的线程任务以及执行完成),执行主线程的代码——》关闭线程池

    ​


    八、创建自定义线程类

            此步骤创建上面描述的线程任务类。

    ​

            实现Callable或者Runable或者继承Thread都行,此处实现Runable,重写run方法。

            根据传入的划分给他的数据区间,将该区间的数据通过subList方法取出来之后,执行上面实现的批量插入方法进行数据的入库操作。为了防止代码出现问题不执行coutDown方法,将该句代码写入finally。

    PS:CountDownLatch的两个方法(countDown,await)配合使用,保证每个线程的代码执行时,主线程进入等待,然后等各个线程任务执行完后,又回到主线程进行执行。


    九、测试单线程和多线程处理的效率

            上面已经完成了单线程和多线程事件监听器的编写,下面开始测试两者的效率。

    1、使用单线程事件监听器

    ​

    ​

    ​

    ​

    ​  

    ​

            结果:100033条数据,数据正确。 

    2、使用多线程事件监听器

    ​

    ​

    ​

            结果:100033条数据,数据正确,确实快了很多。


            我觉得对于业务简单的多线程处理类似场景的都可以拿这个demo拿去改造一下,如果有问题,谢谢大家指出。瑞思拜。

  • 相关阅读:
    力扣:583. 两个字符串的删除操作
    Old Graphics Software
    Spring Cloud配置中心原理
    一条 SQL 更新语句如何执行的
    频响测试低12dB问题
    【HTTP】URL结构、HTTP请求和响应的报文格式、HTTP请求的方法、常见的状态码、GET和POST有什么区别、Cookie、Session等重点知识汇总
    一文梳理Vue面试题
    大富豪3(GM商城版)新手攻略之购买土地
    dataprp库本地参数
    ​LeetCode解法汇总2490. 回环句
  • 原文地址:https://blog.csdn.net/weixin_56995925/article/details/125944749
  • 最新文章
  • 攻防演习之三天拿下官网站群
    数据安全治理学习——前期安全规划和安全管理体系建设
    企业安全 | 企业内一次钓鱼演练准备过程
    内网渗透测试 | Kerberos协议及其部分攻击手法
    0day的产生 | 不懂代码的"代码审计"
    安装scrcpy-client模块av模块异常,环境问题解决方案
    leetcode hot100【LeetCode 279. 完全平方数】java实现
    OpenWrt下安装Mosquitto
    AnatoMask论文汇总
    【AI日记】24.11.01 LangChain、openai api和github copilot
  • 热门文章
  • 十款代码表白小特效 一个比一个浪漫 赶紧收藏起来吧!!!
    奉劝各位学弟学妹们,该打造你的技术影响力了!
    五年了,我在 CSDN 的两个一百万。
    Java俄罗斯方块,老程序员花了一个周末,连接中学年代!
    面试官都震惊,你这网络基础可以啊!
    你真的会用百度吗?我不信 — 那些不为人知的搜索引擎语法
    心情不好的时候,用 Python 画棵樱花树送给自己吧
    通宵一晚做出来的一款类似CS的第一人称射击游戏Demo!原来做游戏也不是很难,连憨憨学妹都学会了!
    13 万字 C 语言从入门到精通保姆级教程2021 年版
    10行代码集2000张美女图,Python爬虫120例,再上征途
Copyright © 2022 侵权请联系2656653265@qq.com    京ICP备2022015340号-1
正则表达式工具 cron表达式工具 密码生成工具

京公网安备 11010502049817号