Java 使用线程把数据库导出为excel

简介: 这是一个demo,内有不足请谅解

这个demo的主题是 使用EasyExcel把数据库导出为excel,多少条为一个excel文件,并把这些文件打包到一个固定位置,然后下载这个包文件

目前各种参数都是写死的,使用的是 生产消费者模式  在一个队列中放数据,取数据。

放一下关键代码:

启动项目时启动一个线程:

@Component//被spring容器管理publicclassMyApplicationRunnerimplementsApplicationRunner {
@Overridepublicvoidrun(ApplicationArgumentsargs) throwsException {
System.out.println("-------------->"+"项目启动,now="+newDate());
ExcelThread.startExcelThread();
    }
}

这是一个全局的阻塞队列:

publicclassQueueUtil {
publicstaticBlockingQueue<Object>queue=newLinkedBlockingQueue<>();
publicstaticObjectget() throwsException{
//        return queue.poll(2, TimeUnit.SECONDS); //不阻塞returnqueue.take(); //阻塞    }
publicstaticvoidput(Objectobj) throwsException{
queue.put(obj);
    }
}

这是Controller   中的导出方法,传一个表名进来,条件可选:

@RequestMapping(value= {"/export/{tableName}"})
publicvoidexport(@PathVariableStringtableName ,Stringname){
//        System.out.println(tableName+"---"+name.length());  user---0if (name.length()==0){
service.exportZIP(tableName);
        }else {
service.exportZIP(tableName, name);
        }
    }

这是Service  这里往队列中存入数据:

publicvoidexportZIP(StringtableName){
try {
QueueUtil.put(tableName);
    }catch (Exceptione){
e.printStackTrace();
System.out.println("存入数据失败");
    }
}
publicvoidexportZIP(StringtableName,Stringname){
try {
QueueUtil.put(tableName+":"+name);
    }catch (Exceptione){
e.printStackTrace();
System.out.println("存入数据失败");
    }
}

线程类  在这把队列中的数据取出来:

publicclassExcelThreadextendsThread{
privatestaticStringPATH="/file/";
privatestaticStringExcelName="用户信息表";
privatestaticStringTYPE=".xlsx";
//    @Value("${zip.name}")privatestaticStringZIP_NAME="用户信息";
privatestaticintSIZE=5000 ;
privateBlockingQueuequeue=QueueUtil.queue;
publicstaticExcelThreadexcelThread=null;
privateFilesServicefilesservice= (FilesService) ApplicationContextUtil.getBean("filesServiceImpl");
publicstaticvoidstartExcelThread(){
if (excelThread==null){
excelThread=newExcelThread();
        }
excelThread.start();
    }
@Overridepublicvoidrun() {
try {
while (true) {
Stringstr= (String) QueueUtil.get(); //《============String[] split=str.split(":");
zip(split);
            }
        } catch (Exceptione) {
e.printStackTrace();
        }
    }
publicvoidzip(String[] str) {
OutputStreamoutputStream;
ZipOutputStreamzipOutputStream;
Serviceservice= (Service) ApplicationContextUtil.getBean(str[0]+"ServiceImpl");
longdate=System.currentTimeMillis();
ZIP_NAME+=date;
Stringpath=System.getProperty("user.dir") +PATH+ZIP_NAME+".zip";
filesservice.alter();
intid=filesservice.save(newFiles(ZIP_NAME,newDate(date)));
try {
outputStream=newFileOutputStream(path);
zipOutputStream=newZipOutputStream(outputStream);
intcount=0;
if (str.length>1){
count=service.count(str[1]);
            }else {
count=service.count();
            }
count=count/SIZE+(count%SIZE==0?0:1);
for (Integeri=0; i<count; i++) {
byte[] buf=newbyte[1024];
List<User>userList;
if (str.length>1){
userList=service.selectPage(i+1,5000,str[1]);
                }else {
userList=service.selectPage(i+1,5000).getRecords();
                }
byte[] content=newFileUtil().excelTableStream(userList).toByteArray(); //返回一个excel文件ByteArrayInputStreamis=newByteArrayInputStream(content);
BufferedInputStreambis=newBufferedInputStream(is);
zipOutputStream.putNextEntry(newZipEntry(ExcelName+(i+1)+TYPE)); //压缩文件条目intlen;
while ((len=bis.read(buf)) >0) {
zipOutputStream.write(buf, 0, len);
                }
zipOutputStream.closeEntry();
bis.close();
is.close();
zipOutputStream.flush();
System.out.println(ExcelName+(i+1)+TYPE+"导出完成");
            }
zipOutputStream.close();
outputStream.close();
        } catch (Exceptione) {
e.printStackTrace();
        }finally {
filesservice.updateState(id,PATH+ZIP_NAME+".zip");
        }
    }
publicstaticvoidmain(String[] args) {
Datenow=newDate(); // 创建一个Date对象,获取当前时间// 指定格式化格式SimpleDateFormatf=newSimpleDateFormat("yyyy年MM月dd日 HH点mm分ss秒");
System.out.println(f.format(now)); // 将当前时间袼式化为指定的格式    }
}

把一个结果集生产一个excel:

publicByteArrayOutputStreamexcelTableStream(List<User>userList) {
try {
ByteArrayOutputStreambyteArrayOutputStream=newByteArrayOutputStream();
EasyExcel.write(byteArrayOutputStream, User.class)
//.registerWriteHandler(new LongestMatchColumnWidthStyleStrategy()) 自动列宽  数字不起作用                .sheet("用户信息")
                .doWrite(() -> {
// 查询数据returnuserList;
                });
returnbyteArrayOutputStream;
    } catch (Exceptione) {
e.printStackTrace();
    }
returnnull;
}


先上效果图,在列表页面点击导出按钮,然后在一个文件表中添加一条数据,查看导出状态,完成后有一个下载地址

image.png

image.png

目录
相关文章
|
5天前
|
监控 Java
java异步判断线程池所有任务是否执行完
通过上述步骤,您可以在Java中实现异步判断线程池所有任务是否执行完毕。这种方法使用了 `CompletionService`来监控任务的完成情况,并通过一个独立线程异步检查所有任务的执行状态。这种设计不仅简洁高效,还能确保在大量任务处理时程序的稳定性和可维护性。希望本文能为您的开发工作提供实用的指导和帮助。
44 17
|
16天前
|
Java
Java—多线程实现生产消费者
本文介绍了多线程实现生产消费者模式的三个版本。Version1包含四个类:`Producer`(生产者)、`Consumer`(消费者)、`Resource`(公共资源)和`TestMain`(测试类)。通过`synchronized`和`wait/notify`机制控制线程同步,但存在多个生产者或消费者时可能出现多次生产和消费的问题。 Version2将`if`改为`while`,解决了多次生产和消费的问题,但仍可能因`notify()`随机唤醒线程而导致死锁。因此,引入了`notifyAll()`来唤醒所有等待线程,但这会带来性能问题。
Java—多线程实现生产消费者
|
1天前
|
缓存 安全 算法
Java 多线程 面试题
Java 多线程 相关基础面试题
|
12天前
|
关系型数据库 MySQL Linux
Linux下mysql数据库的导入与导出以及查看端口
本文详细介绍了在Linux下如何导入和导出MySQL数据库,以及查看MySQL运行端口的方法。通过这些操作,用户可以轻松进行数据库的备份与恢复,以及确认MySQL服务的运行状态和端口。掌握这些技能,对于日常数据库管理和维护非常重要。
57 8
|
18天前
|
安全 Java Kotlin
Java多线程——synchronized、volatile 保障可见性
Java多线程中,`synchronized` 和 `volatile` 关键字用于保障可见性。`synchronized` 保证原子性、可见性和有序性,通过锁机制确保线程安全;`volatile` 仅保证可见性和有序性,不保证原子性。代码示例展示了如何使用 `synchronized` 和 `volatile` 解决主线程无法感知子线程修改共享变量的问题。总结:`volatile` 确保不同线程对共享变量操作的可见性,使一个线程修改后,其他线程能立即看到最新值。
|
14天前
|
存储 Java easyexcel
招行面试:100万级别数据的Excel,如何秒级导入到数据库?
本文由40岁老架构师尼恩撰写,分享了应对招商银行Java后端面试绝命12题的经验。文章详细介绍了如何通过系统化准备,在面试中展示强大的技术实力。针对百万级数据的Excel导入难题,尼恩推荐使用阿里巴巴开源的EasyExcel框架,并结合高性能分片读取、Disruptor队列缓冲和高并发批量写入的架构方案,实现高效的数据处理。此外,文章还提供了完整的代码示例和配置说明,帮助读者快速掌握相关技能。建议读者参考《尼恩Java面试宝典PDF》进行系统化刷题,提升面试竞争力。关注公众号【技术自由圈】可获取更多技术资源和指导。
|
18天前
|
消息中间件 缓存 安全
Java多线程是什么
Java多线程简介:本文介绍了Java中常见的线程池类型,包括`newCachedThreadPool`(适用于短期异步任务)、`newFixedThreadPool`(适用于固定数量的长期任务)、`newScheduledThreadPool`(支持定时和周期性任务)以及`newSingleThreadExecutor`(保证任务顺序执行)。同时,文章还讲解了Java中的锁机制,如`synchronized`关键字、CAS操作及其实现方式,并详细描述了可重入锁`ReentrantLock`和读写锁`ReadWriteLock`的工作原理与应用场景。
|
18天前
|
存储 Oracle 关系型数据库
数据库传奇:MySQL创世之父的两千金My、Maria
《数据库传奇:MySQL创世之父的两千金My、Maria》介绍了MySQL的发展历程及其分支MariaDB。MySQL由Michael Widenius等人于1994年创建,现归Oracle所有,广泛应用于阿里巴巴、腾讯等企业。2009年,Widenius因担心Oracle收购影响MySQL的开源性,创建了MariaDB,提供额外功能和改进。维基百科、Google等已逐步替换为MariaDB,以确保更好的性能和社区支持。掌握MariaDB作为备用方案,对未来发展至关重要。
45 3
|
18天前
|
安全 关系型数据库 MySQL
MySQL崩溃保险箱:探秘Redo/Undo日志确保数据库安全无忧!
《MySQL崩溃保险箱:探秘Redo/Undo日志确保数据库安全无忧!》介绍了MySQL中的三种关键日志:二进制日志(Binary Log)、重做日志(Redo Log)和撤销日志(Undo Log)。这些日志确保了数据库的ACID特性,即原子性、一致性、隔离性和持久性。Redo Log记录数据页的物理修改,保证事务持久性;Undo Log记录事务的逆操作,支持回滚和多版本并发控制(MVCC)。文章还详细对比了InnoDB和MyISAM存储引擎在事务支持、锁定机制、并发性等方面的差异,强调了InnoDB在高并发和事务处理中的优势。通过这些机制,MySQL能够在事务执行、崩溃和恢复过程中保持
47 3
|
18天前
|
SQL 关系型数据库 MySQL
数据库灾难应对:MySQL误删除数据的救赎之道,技巧get起来!之binlog
《数据库灾难应对:MySQL误删除数据的救赎之道,技巧get起来!之binlog》介绍了如何利用MySQL的二进制日志(Binlog)恢复误删除的数据。主要内容包括: 1. **启用二进制日志**:在`my.cnf`中配置`log-bin`并重启MySQL服务。 2. **查看二进制日志文件**:使用`SHOW VARIABLES LIKE &#39;log_%&#39;;`和`SHOW MASTER STATUS;`命令获取当前日志文件及位置。 3. **创建数据备份**:确保在恢复前已有备份,以防意外。 4. **导出二进制日志为SQL语句**:使用`mysqlbinlog`
62 2