整体流程
    1.依赖jar
    2.定义要写成的类
    3.写出Excel
    调用方法完成生成Excel
    EasyExcel.write(“路径或者输出流”,类对应的Class对象).sheet().doWirte(集合);
    4.读取Excel
    1.根据模板数据封装类,属性和列数据一一对应,使用@ExcelProperty标记表格中列名
    2.定义读取监听器,创建类实现ReadListener接口,重写方法,获取读取到的内容
    3.调用方法完成读取
    EasyExcel.read(“路径或输入流”,封装类的Class,自定义监听器对象).sheet().doRead();
    1.jar包

    1. <dependency>
    2. <groupId>com.alibaba</groupId>
    3. <artifactId>easyexcel</artifactId>
    4. <version>3.0.5</version>
    5. </dependency>

    2.配置文件
    //springMVC.xml里面

    1. <!-- 配置文件上传 -->
    2. <bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
    3. <!-- 最大可上传的文件大小 单位:byte 超出后会抛出MaxUploadSizeExceededException异常,可以异常解析器捕获 -->
    4. <property name="maxUploadSize" value="1048576"/>
    5. </bean>

    3.配置线程池在工具包里面
    ThreadPoolSingle类

    1. package com.qyz.common.util;
    2. import java.util.concurrent.ArrayBlockingQueue;
    3. import java.util.concurrent.Executors;
    4. import java.util.concurrent.ThreadPoolExecutor;
    5. import java.util.concurrent.TimeUnit;
    6. public class ThreadPoolSingle {
    7. public ThreadPoolExecutor poolExecutor;//原生的线程池对象
    8. //私有构造器
    9. private ThreadPoolSingle(){
    10. poolExecutor=new ThreadPoolExecutor(4,10,
    11. 3, TimeUnit.SECONDS,
    12. new ArrayBlockingQueue<>(20),
    13. Executors.defaultThreadFactory(),
    14. new ThreadPoolExecutor.AbortPolicy());
    15. }
    16. //静态内部类
    17. static class ThreadPoolSingleFactory{
    18. public static ThreadPoolSingle single=new ThreadPoolSingle();
    19. }
    20. //公有静态方法
    21. public static ThreadPoolSingle getInstance(){
    22. return ThreadPoolSingleFactory.single;
    23. }
    24. //新增任务
    25. public void addTask(Runnable runnable){
    26. poolExecutor.submit(runnable);
    27. }
    28. }

    解释
    单例模式:
    作用:创建类的对象,唯一对象
    实现方式:
    1.懒汉式
    2.饿汉式
    3.双锁
    4.IoDH(静态内部类)
    5.枚举
    4.线程池
    池化技术:1.提高复用率 2.控制数量
    线程池:可以提高线程的使用率,还可以有效控制线程的数量
    实际开发中,使用线程的话,都是使用线程池,而且用原生线程池

    poolExecutor=new ThreadPoolExecutor(
        核心线程数 最小线程数(不回收)
        4,
        最大线程数
        10,
        空闲时间
        3, 
        空闲的时间单位,分钟
        TimeUnit.SECONDS,
        阻塞队列 7种
                    new ArrayBlockingQueue<>(20),
        线程创建工厂
                    Executors.defaultThreadFactory(),
        拒绝策略,4种
                    new ThreadPoolExecutor.AbortPolicy());
    1.先触发核心线程数 2.添加到阻塞队列 3.触发最大线程数 4.触发拒绝策略*/
    

    4.设置监听工具类
    AdminReadListener在listener包里面

    package com.qyz.common.listener;
    
    
    import com.alibaba.excel.context.AnalysisContext;
    import com.alibaba.excel.read.listener.ReadListener;
    import com.qyz.common.util.ThreadPoolSingle;
    import com.qyz.dao.AdminDao;
    import com.qyz.entity.Admin;
    
    import java.util.ArrayList;
    import java.util.List;
    
    /**
     * @author Feri
     * @date 2021/12/20 14:51
     * @description:TODO
     */
    public class AdminReadListener implements ReadListener<Admin> {
        private AdminDao dao;
        public AdminReadListener(AdminDao dao){
            this.dao = dao;
        }
        //初始容量
        private List<Admin> list = new ArrayList<>(1010);
        //读取的每一行
        @Override
        public void invoke(Admin admin, AnalysisContext analysisContext) {
            list.add(admin);
            if(list.size() >= 1000){
                //实现集合的复制,把需要线程池干的集合生成出来
                List<Admin> child = new ArrayList<>(list);
                //list代码清空复用list集合放止list调用自增方法减少效率
                list.clear();//清理原集合
                //执行批处理
                ThreadPoolSingle.getInstance().addTask(()->{
                    dao.insertBatch(child);
                });
            }
        }
        //整个表格读取结束
        @Override
        public void doAfterAllAnalysed(AnalysisContext analysisContext) {
            //执行最后不足1000条的数据
            dao.insertBatch(list);
        }
    }
    

    6设置Controller里面的url

    @RequestMapping(value = "/upload.do",method = {RequestMethod.POST})
    @ResponseBody
    public JsonResult upload(MultipartFile file) throws IOException {
        return service.saveBatchV2(file);
    }
    

    7.设置实体类属性和表格字段的匹配

        private Integer id;
        @ExcelProperty("账号")
        private String name;
        @ExcelProperty("密码")
        private String password;
        @ExcelProperty("状态")
        private Integer flag;
        private Date ctime;
    

    8.设置service层的代码
    数据量比较大的时候使用这个

        //可以抗住大文件的上传
        @Override
        public JsonResult saveBatchV2(MultipartFile file) throws IOException {
            //将上传的内容解析并添加到数据库
            EasyExcel.read(
                    file.getInputStream(),//上传的文件内容-Excel表格
                    Admin.class,//每一行对应的类型
                    new AdminReadListener(dao)).sheet().doRead();
            return JsonResult.success(null);
        }
    

    8.设置service层的代码
    数据量较小的时候使用

        @Override
        public JsonResult saveBatch(MultipartFile file) throws IOException {
            //将上传的内容解析并添加到数据库
            EasyExcel.read(
                    file.getInputStream(),//上传的文件内容-Excel表格
                    Admin.class,//每一行对应的类型
                    new PageReadListener(list -> {//获取的数据
                        dao.insertBatch((List<Admin>) list);
                    })).sheet().doRead();
            return JsonResult.success(null);
        }
    

    9.设置dao层的映射方法

        //批量新增
        int insertBatch(List<Book> list);
    

    10.设置mapper的sql语句实现数据的

        <insert id="insertBatch" parameterType="list">
            insert into admin(name,password,flag,ctime) values
            <foreach collection="list" item="a" separator=",">
                (#{a.name},#{a.password},#{a.flag},now())
            </foreach>
        </insert>
    

    数据库数据的批量下载
    Controller

        @RequestMapping(value = "/download.do",method = {RequestMethod.GET})
        public void download(HttpServletResponse response) throws IOException {
            service.download(response);
        }
    

    service层

        @Override
        public void download(HttpServletResponse response) throws IOException {
            //设置响应头信息
            response.setContentType("application/vnd.ms-excel");
            response.setCharacterEncoding("utf-8");
            response.setHeader("Content-disposition", "attachment;filename=" + System.currentTimeMillis() + ".xlsx");
            //基于EasyExcel实现Excel表格的生成
            EasyExcel.write(response.getOutputStream(), Admin.class).sheet("自动导出").doWrite(dao.selectAll());
        }