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

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


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

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

效果:


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

       首先看下目录结构

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

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

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


一、准备数据库和Excel文件

CREATE TABLE `deadman` (
  `uid` varchar(255) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL COMMENT '主键',
  `idCard` varchar(255) CHARACTER SET utf8 COLLATE utf8_bin DEFAULT NULL COMMENT '身份证号',
  `userName` varchar(255) CHARACTER SET utf8 COLLATE utf8_bin DEFAULT NULL COMMENT '死者姓名',
  `sex` varchar(255) CHARACTER SET utf8 COLLATE utf8_bin DEFAULT NULL COMMENT '死者性别',
  `age` varchar(255) CHARACTER SET utf8 COLLATE utf8_bin DEFAULT NULL COMMENT '死者年龄',
  `reason` varchar(255) CHARACTER SET utf8 COLLATE utf8_bin DEFAULT NULL COMMENT '死因',
  `house` varchar(255) CHARACTER SET utf8 COLLATE utf8_bin DEFAULT NULL COMMENT '安排地狱层数',
  PRIMARY KEY (`uid`)
) 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拿去改造一下,如果有问题,谢谢大家指出。瑞思拜。

目录
相关文章
|
5天前
|
JSON Java 数据格式
微服务——SpringBoot使用归纳——Spring Boot返回Json数据及数据封装——封装统一返回的数据结构
本文介绍了在Spring Boot中封装统一返回的数据结构的方法。通过定义一个泛型类`JsonResult<T>`,包含数据、状态码和提示信息三个属性,满足不同场景下的JSON返回需求。例如,无数据返回时可设置默认状态码"0"和消息"操作成功!",有数据返回时也可自定义状态码和消息。同时,文章展示了如何在Controller中使用该结构,通过具体示例(如用户信息、列表和Map)说明其灵活性与便捷性。最后总结了Spring Boot中JSON数据返回的配置与实际项目中的应用技巧。
43 0
|
5天前
|
JSON Java fastjson
微服务——SpringBoot使用归纳——Spring Boot返回Json数据及数据封装——使用 fastJson 处理 null
本文介绍如何使用 fastJson 处理 null 值。与 Jackson 不同,fastJson 需要通过继承 `WebMvcConfigurationSupport` 类并覆盖 `configureMessageConverters` 方法来配置 null 值的处理方式。例如,可将 String 类型的 null 转为 "",Number 类型的 null 转为 0,避免循环引用等。代码示例展示了具体实现步骤,包括引入相关依赖、设置序列化特性及解决中文乱码问题。
21 0
|
5天前
|
JSON Java fastjson
微服务——SpringBoot使用归纳——Spring Boot返回Json数据及数据封装——Spring Boot 默认对Json的处理
本文介绍了在Spring Boot中返回Json数据的方法及数据封装技巧。通过使用`@RestController`注解,可以轻松实现接口返回Json格式的数据,默认使用的Json解析框架是Jackson。文章详细讲解了如何处理不同数据类型(如类对象、List、Map)的Json转换,并提供了自定义配置以应对null值问题。此外,还对比了Jackson与阿里巴巴FastJson的特点,以及如何在项目中引入和配置FastJson,解决null值转换和中文乱码等问题。
22 0
|
12天前
|
前端开发 Cloud Native Java
Java||Springboot读取本地目录的文件和文件结构,读取服务器文档目录数据供前端渲染的API实现
博客不应该只有代码和解决方案,重点应该在于给出解决方案的同时分享思维模式,只有思维才能可持续地解决问题,只有思维才是真正值得学习和分享的核心要素。如果这篇博客能给您带来一点帮助,麻烦您点个赞支持一下,还可以收藏起来以备不时之需,有疑问和错误欢迎在评论区指出~
Java||Springboot读取本地目录的文件和文件结构,读取服务器文档目录数据供前端渲染的API实现
|
1月前
|
Linux
Linux编程: 在业务线程中注册和处理Linux信号
本文详细介绍了如何在Linux中通过在业务线程中注册和处理信号。我们讨论了信号的基本概念,并通过完整的代码示例展示了在业务线程中注册和处理信号的方法。通过正确地使用信号处理机制,可以提高程序的健壮性和响应能力。希望本文能帮助您更好地理解和应用Linux信号处理,提高开发效率和代码质量。
56 17
|
1月前
|
Linux
Linux编程: 在业务线程中注册和处理Linux信号
通过本文,您可以了解如何在业务线程中注册和处理Linux信号。正确处理信号可以提高程序的健壮性和稳定性。希望这些内容能帮助您更好地理解和应用Linux信号处理机制。
62 26
|
3月前
|
存储 安全 Java
Java多线程编程秘籍:各种方案一网打尽,不要错过!
Java 中实现多线程的方式主要有四种:继承 Thread 类、实现 Runnable 接口、实现 Callable 接口和使用线程池。每种方式各有优缺点,适用于不同的场景。继承 Thread 类最简单,实现 Runnable 接口更灵活,Callable 接口支持返回结果,线程池则便于管理和复用线程。实际应用中可根据需求选择合适的方式。此外,还介绍了多线程相关的常见面试问题及答案,涵盖线程概念、线程安全、线程池等知识点。
314 2
|
4月前
|
设计模式 Java 开发者
Java多线程编程的陷阱与解决方案####
本文深入探讨了Java多线程编程中常见的问题及其解决策略。通过分析竞态条件、死锁、活锁等典型场景,并结合代码示例和实用技巧,帮助开发者有效避免这些陷阱,提升并发程序的稳定性和性能。 ####
|
4月前
|
缓存 Java 开发者
Java多线程编程的陷阱与最佳实践####
本文深入探讨了Java多线程编程中常见的陷阱,如竞态条件、死锁和内存一致性错误,并提供了实用的避免策略。通过分析典型错误案例,本文旨在帮助开发者更好地理解和掌握多线程环境下的编程技巧,从而提升并发程序的稳定性和性能。 ####
|
3月前
|
缓存 Java 调度
多线程编程核心:上下文切换深度解析
在现代计算机系统中,多线程编程已成为提高程序性能和响应速度的关键技术。然而,多线程编程中一个不可避免的概念就是上下文切换(Context Switching)。本文将深入探讨上下文切换的概念、原因、影响以及优化策略,帮助你在工作和学习中深入理解这一技术干货。
79 10

热门文章

最新文章