zoukankan      html  css  js  c++  java
  • 多线程读表-压缩成zip下载

    1、背景介绍

      读13张表,4000条放到一个excel,打包成zip,并加密下载。本文为Demo版本,实现了多线程导出excel并打包zip提供下载,没有实现每4000条放到一个zip中以及zip加密。

    2、pom.xml

        <dependencies>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-data-jpa</artifactId>
            </dependency>
            <dependency>
                <groupId>junit</groupId>
                <artifactId>junit</artifactId>
                <version>4.11</version>
                <scope>test</scope>
            </dependency>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter</artifactId>
            </dependency>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-web</artifactId>
            </dependency>
            <dependency>
                <groupId>mysql</groupId>
                <artifactId>mysql-connector-java</artifactId>
                <scope>runtime</scope>
            </dependency>
            <dependency>
                <groupId>io.springfox</groupId>
                <artifactId>springfox-swagger2</artifactId>
                <version>2.8.0</version>
            </dependency>
            <dependency>
                <groupId>io.springfox</groupId>
                <artifactId>springfox-swagger-ui</artifactId>
                <version>2.8.0</version>
            </dependency>
            <!-- https://mvnrepository.com/artifact/com.alibaba/druid -->
            <dependency>
                <groupId>com.alibaba</groupId>
                <artifactId>druid</artifactId>
                <version>1.1.22</version>
            </dependency>
            <!--MySQL数据库驱动-->
            <dependency>
                <groupId>javax.jms</groupId>
                <artifactId>javax.jms-api</artifactId>
                <version>2.0.1</version>
            </dependency>
            <dependency>
                <groupId>com.caucho</groupId>
                <artifactId>hessian</artifactId>
                <version>4.0.38</version>
            </dependency>
            <!-- json schema 转换 fge -->
            <dependency>
                <groupId>com.github.fge</groupId>
                <artifactId>json-schema-validator</artifactId>
                <version>2.2.6</version>
            </dependency>
            <!-- mybatis-plus -->
            <dependency>
                <groupId>com.baomidou</groupId>
                <artifactId>mybatis-plus-boot-starter</artifactId>
                <version>3.3.2</version>
            </dependency>
            <dependency>
                <groupId>com.baomidou</groupId>
                <artifactId>mybatis-plus-support</artifactId>
                <version>2.3</version>
            </dependency>
            <dependency>
                <groupId>com.google.code.gson</groupId>
                <artifactId>gson</artifactId>
                <version>2.8.5</version>
            </dependency>
            <dependency>
                <groupId>org.projectlombok</groupId>
                <artifactId>lombok</artifactId>
                <optional>true</optional>
            </dependency>
            <dependency>
                <groupId>com.alibaba</groupId>
                <artifactId>easyexcel</artifactId>
                <version>2.1.6</version>
            </dependency>
        </dependencies>
    

    2、config包下多线程配置类

    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    import org.springframework.beans.factory.annotation.Value;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
    
    import java.util.concurrent.Executor;
    import java.util.concurrent.ThreadPoolExecutor;
    
    @Configuration
    public class ExecutorConfig {
        private static final Logger logger = LoggerFactory.getLogger(ExecutorConfig.class);
        @Value("${task.pool.corePoolSize}")
        private int corePoolSize;
        @Value("${task.pool.maxPoolSize}")
        private int maxPoolSize;
        @Value("${task.pool.keepAliveSeconds}")
        private int keepAliveSeconds;
        @Value("${task.pool.queueCapacity}")
        private int queueCapacity;
        @Value("${task.pool.threadNamePrefix}")
        private String threadNamePrefix;
     
        @Bean
        public Executor asyncExcelServiceExecutor() {
            logger.info("...ExecutorConfig...asyncServiceExecutor()...启动[zip任务]线程池...");
            ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
            executor.setCorePoolSize(corePoolSize);
            executor.setMaxPoolSize(maxPoolSize);
            executor.setThreadNamePrefix(threadNamePrefix);
            executor.setKeepAliveSeconds(keepAliveSeconds);
            executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
            executor.initialize();
            return executor;
        }
    }
    

    3、application-dev.properties多线程设置

    task.pool.corePoolSize=15
    task.pool.maxPoolSize=99
    task.pool.keepAliveSeconds=300
    task.pool.queueCapacity=999
    task.pool.threadNamePrefix=Grape-
    

    4、开启多线程

    @EnableAsync
    @SpringBootApplication
    @MapperScan(basePackages = {"....ry.dao"})
    public class BasicSystem {
        public static void main(String[] args) {
            SpringApplication.run(BasicSystem.class, args);
        }
    }
    

    5、service层方法

    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.stereotype.Service;
    
    import javax.servlet.http.HttpServletResponse;
    import java.io.IOException;
    import java.io.InputStream;
    import java.util.concurrent.CountDownLatch;
    import java.util.zip.ZipOutputStream;
    
    @Service
    public class NOnij {
        @Autowired
        private NOnijAsync nOnijAsync;
    
        public void zip(HttpServletResponse response) throws IOException {
            response.setContentType("application/force-download");
            response.addHeader("Access-Control-Expose-Headers", "Content-Disposition");
            response.setHeader("Content-Disposition", "attachment; filename=" + new String(("sjn-" + DateUtils.getDateTime() + ".zip").getBytes("UTF-8"), "ISO8859-1"));
            ZipOutputStream zipout = new ZipOutputStream(response.getOutputStream());
            InputStream inputStream = null;
    
            try {
                //加闩
                CountDownLatch latch = new CountDownLatch(2);
    
                nOnijAsync.excelUser(latch, zipout, inputStream);
                nOnijAsync.excelProject(latch, zipout, inputStream);
    
                //等待N个线程执行完毕
                latch.await();
                System.out.println("---所有线程---end---");
    
            } catch (InterruptedException e) {
    
            } catch (IOException e) {
                System.out.println(e.getMessage());
            } finally {
                if (zipout != null) {
                    zipout.close();
                }
                if (inputStream != null) {
                    inputStream.close();
                }
            }
        }
    }
    

    6、多线程方法

    import com.alibaba.excel.EasyExcel;
    import com.alibaba.excel.ExcelWriter;
    import com.alibaba.excel.write.metadata.WriteSheet;
    import com.baomidou.mybatisplus.plugins.Page;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.scheduling.annotation.Async;
    import org.springframework.stereotype.Component;
    
    import java.io.ByteArrayInputStream;
    import java.io.ByteArrayOutputStream;
    import java.io.IOException;
    import java.io.InputStream;
    import java.util.List;
    import java.util.concurrent.CountDownLatch;
    import java.util.concurrent.Future;
    import java.util.zip.ZipEntry;
    import java.util.zip.ZipOutputStream;
    
    @Component
    public class NOnijAsync {
        @Autowired
        private UserMapper userMapper;
        @Autowired
        private ProductMapper productMapper;
    
        @Async("asyncExcelServiceExecutor")
        public void excelProject(CountDownLatch latch, ZipOutputStream zipout, InputStream inputStream) throws IOException {
            String currentThreadName = Thread.currentThread().getName();
            System.out.println("---线程: 【" + currentThreadName + "】 ---start---Project---");
    
            //分页查询数据,然后放到循环中进行写表
    
            List<Product> products = productMapper.selectList(null);
            products.add(new Product("小明", "21"));
            products.add(new Product("小明", "21"));
            products.add(new Product("小明", "21"));
            products.add(new Product("小明", "21"));
            products.add(new Product("小明", "21"));
    
            getZip(products, zipout, inputStream, Product.class, "project");
    
            latch.countDown();
    
        }
    
        @Async("asyncExcelServiceExecutor")
        public Future<List<Page>> excelUser(CountDownLatch latch, ZipOutputStream zipout, InputStream inputStream) throws IOException {
            String currentThreadName = Thread.currentThread().getName();
            System.out.println("---线程: 【" + currentThreadName + "】 ---start---User---");
    
            List<User> users = userMapper.selectList(null);
            users.add(new User("小丽", "18"));
            users.add(new User("小丽", "18"));
            users.add(new User("小丽", "18"));
            users.add(new User("小丽", "18"));
            users.add(new User("小丽", "18"));
            users.add(new User("小丽", "18"));
    
            getZip(users, zipout, inputStream, User.class, "user");
    
            latch.countDown();
    
            return null;
        }
    
        private void getZip(List datas, ZipOutputStream zipout, InputStream inputStream, Class clazz, String excelName) throws IOException {
            //sheetName页名称
            String sheetName1 = "sheet1";
            ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
            ExcelWriter writer = EasyExcel.write(outputStream, clazz).build();
            WriteSheet writeSheet = EasyExcel.writerSheet(sheetName1).build();
            //导出excel
            writer.write(datas, writeSheet);
            writer.finish();
            inputStream = new ByteArrayInputStream(outputStream.toByteArray());
            //excel文件写入zip
            ZipEntry zipEntry = new ZipEntry(excelName + DateUtils.getDateTime() + ".xlsx");///DateUtils.getDateTime()线程非安全
            zipout.putNextEntry(zipEntry);
            int len;
            byte[] buf = new byte[1024];
            while ((len = inputStream.read(buf)) > 0) {
                zipout.write(buf, 0, len);
            }
        }
    }

    参考:

    https://blog.csdn.net/qq_35493807/article/details/105613898

    参考2:

    @Controller
    public class TestExportZipController {
        @GetMapping("/111")
        public void export(HttpServletResponse response) throws IOException {
            response.setContentType("application/force-download");
            response.addHeader("Access-Control-Expose-Headers", "Content-Disposition");
            response.setHeader("Content-Disposition", "attachment; filename=" + new String(("sjn-" + DateUtils.getDateTime() + ".zip").getBytes("UTF-8"), "ISO8859-1"));
            ZipOutputStream zipout = new ZipOutputStream(response.getOutputStream());
            InputStream inputStream = null;
    
            try {
                for (int i = 0; i < 3; i++) {
                    ArrayList<UserVO> userVOList = new ArrayList<>();
                    userVOList.add(new UserVO("haha", 1));
                    userVOList.add(new UserVO("haha2", 12));
                    userVOList.add(new UserVO("haha4", 14));
                    userVOList.add(new UserVO("haha3", 13));
                    userVOList.add(new UserVO("haha5", 15));
    
                    //sheetName页名称
                    String sheetName = "sheetName";
                    ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
                    ExcelWriter writer = EasyExcel.write(outputStream, UserVO.class).build();
                    WriteSheet writeSheet = EasyExcel.writerSheet(sheetName).build();
                    //导出excel
                    writer.write(userVOList, writeSheet);
                    writer.finish();
                    inputStream = new ByteArrayInputStream(outputStream.toByteArray());
                    //excel文件写入zip
                    ZipEntry zipEntry = new ZipEntry(DateUtils.getDateTime() + "-" + i + ".xlsx");
                    zipout.putNextEntry(zipEntry);
                    int len;
                    byte[] buf = new byte[1024];
                    while ((len = inputStream.read(buf)) > 0) {
                        zipout.write(buf, 0, len);
                    }
                }
    
            } catch (IOException e) {
                System.out.println(e.getMessage());
            } finally {
                if (zipout != null) {
                    zipout.close();
                }
                if (inputStream != null) {
                    inputStream.close();
                }
            }
    
        }
    }
    

      

  • 相关阅读:
    麻省理工算法导论学习笔记(1)算法介绍
    麻省理工算法导论学习笔记(2)渐近符号、递归及解法
    Mybatis if 标签 判断不生效
    Linux permission denied解决方法?
    MySQL查找是否存在
    List集合数据去重
    Java获取list集合的前几个元素
    git如何新建(修改)分支
    asp.net下url参数含有中文读取后为乱码
    时间复杂度为O(n)的排序算法
  • 原文地址:https://www.cnblogs.com/songjn/p/13410026.html
Copyright © 2011-2022 走看看