Java 将数据导出到Excel并发送到在线文档

一、需求

现将列表数据,导出到excel,并将文件发送到在线文档,摒弃了以往的直接在前端下载的老旧模式。

二、pom依赖

        <!-- redission --><dependency><groupId>org.redisson</groupId><artifactId>redisson-spring-boot-starter</artifactId><version>3.14.0</version><exclusions><exclusion><groupId>org.redisson</groupId><artifactId>redisson-spring-data-23</artifactId></exclusion></exclusions></dependency><dependency><groupId>org.redisson</groupId><artifactId>redisson-spring-data-20</artifactId><version>3.14.0</version></dependency><dependency><groupId>com.alibaba</groupId><artifactId>fastjson</artifactId><version>1.2.83</version></dependency><!-- easyexcel 主要依赖  这一个基本上就够了--><dependency><groupId>com.alibaba</groupId><artifactId>easyexcel</artifactId><version>2.1.4</version></dependency><dependency><groupId>commons-io</groupId><artifactId>commons-io</artifactId><version>2.4</version></dependency>

三、定义表实体

import com.fasterxml.jackson.annotation.JsonFormat;import java.util.Date;
import java.util.Objects;/*** @Author: * @Description* @Date: 下午5:18 2023/10/26*/
public class EntityData {private String name;private String code;private Double score;private Integer age;private String phone;@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")private Date createTime;public EntityData() {}public EntityData(String name, String code, Double score, Integer age, String phone, Date createTime) {this.name = name;this.code = code;this.score = score;this.age = age;this.phone = phone;this.createTime = createTime;}public String getName() {return name;}public void setName(String name) {this.name = name;}public String getCode() {return code;}public void setCode(String code) {this.code = code;}public Double getScore() {return score;}public void setScore(Double score) {this.score = score;}public Integer getAge() {return age;}public void setAge(Integer age) {this.age = age;}public String getPhone() {return phone;}public void setPhone(String phone) {this.phone = phone;}public Date getCreateTime() {return createTime;}public void setCreateTime(Date createTime) {this.createTime = createTime;}@Overridepublic boolean equals(Object o) {if (this == o) return true;if (o == null || getClass() != o.getClass()) return false;EntityData that = (EntityData) o;return Objects.equals(name, that.name) &&Objects.equals(code, that.code) &&Objects.equals(score, that.score) &&Objects.equals(age, that.age) &&Objects.equals(phone, that.phone) &&Objects.equals(createTime, that.createTime);}@Overridepublic int hashCode() {return Objects.hash(name, code, score, age, phone, createTime);}@Overridepublic String toString() {return "EntityData{" +"name='" + name + '\'' +", code='" + code + '\'' +", score=" + score +", age=" + age +", phone='" + phone + '\'' +", createTime=" + createTime +'}';}
}

四、定义写入Excel实体

import com.alibaba.excel.annotation.ExcelProperty;
import com.fasterxml.jackson.annotation.JsonFormat;import java.util.Date;
import java.util.Objects;/*** @Author:* @Description* @Date: 下午5:18 2023/10/26*/
public class ExcelData {@ExcelProperty(value = "姓名")private String name;@ExcelProperty(value = "学号")private String code;@ExcelProperty(value = "分数")private Double score;@ExcelProperty(value = "统计时间")@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")private Date createTime;public ExcelData() {}public ExcelData(String name, String code, Double score, Date createTime) {this.name = name;this.code = code;this.score = score;this.createTime = createTime;}public String getName() {return name;}public void setName(String name) {this.name = name;}public String getCode() {return code;}public void setCode(String code) {this.code = code;}public Double getScore() {return score;}public void setScore(Double score) {this.score = score;}public Date getCreateTime() {return createTime;}public void setCreateTime(Date createTime) {this.createTime = createTime;}@Overridepublic boolean equals(Object o) {if (this == o) return true;if (o == null || getClass() != o.getClass()) return false;ExcelData excelData = (ExcelData) o;return Objects.equals(name, excelData.name) &&Objects.equals(code, excelData.code) &&Objects.equals(score, excelData.score) &&Objects.equals(createTime, excelData.createTime);}@Overridepublic int hashCode() {return Objects.hash(name, code, score, createTime);}@Overridepublic String toString() {return "ExcelData{" +"name='" + name + '\'' +", code='" + code + '\'' +", score=" + score +", createTime=" + createTime +'}';}
}

五、定义接口

import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;/*** @Author: * @Description* @Date: 下午4:45 2023/10/26*/
@RestController
@RequestMapping("/file")
public interface FileApi {@GetMapping(path = "/export")ResponseData<String> export();}

六、定义service

import com.alibaba.excel.EasyExcel;
import com.example.exception.CustomException;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;import javax.annotation.Resource;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.concurrent.TimeUnit;/*** @Author:* @Description* @Date: 下午4:45 2023/10/26*/
@Service
public class FileService implements FileApi {@Resourceprivate RedissonClient redissonClient; //这里使用redisson分布式锁 需要导入pom依赖和spring配置private static final String DOWNLOAD_EXCEL_SHEETS_KEY = "download:";@Autowiredprivate ThreadPoolTaskExecutor taskExecutor;@Overridepublic ResponseData<String> export() {//TODO 条件允许的话获取当前登录人信息作为redis key 的一部分,请自行填充String token = "";//加锁 防重复下载RLock lock = redissonClient.getLock(DOWNLOAD_EXCEL_SHEETS_KEY + token);try {if (lock.isLocked()) {throw new CustomException("您当前有导出中的任务尚未完成,请稍后再试!");}//这里使用看门狗机制 等待5秒,-1即开启看门狗boolean flag = lock.tryLock(5, -1, TimeUnit.SECONDS);//占用失败,抛出异常if (!flag) {throw new CustomException("锁定导出失败");}//模拟查询列表数据,可以从数据库查询List<EntityData> list = new ArrayList<>();list.add(new EntityData("张三", "001", 78.72, 11, "159888888888", new Date()));list.add(new EntityData("李四", "002", 45.87, 12, "159888888777", new Date()));list.add(new EntityData("王五", "003", 83.5, 13, "159888888666", new Date()));//判断列表数据是否为空if (CollectionUtils.isEmpty(list)) {throw new CustomException("列表没有数据!");}//异步导出 注意这里使用的异步操作,如果需要一些本地变量,如用户token信息,需要当参数透传taskExecutor.submit(() -> this.convertTExpConfirmationSheetExcel(list, "user"));} catch (InterruptedException ee) {Thread.currentThread().interrupt();} catch (CustomException eee) {throw new CustomException(eee.getMessage());} catch (Exception e) {throw new CustomException("导出出错");} finally {lock.unlock();}return ResponseData.ok("请稍后到XXXX查看");}/*** 确认单列表导出逻辑处理** @param data* @param currentUser*/private void convertTExpConfirmationSheetExcel(List<EntityData> data, String currentUser) {List<ExcelData> excelDataList = new ArrayList<>();//将数据拼装为导出数据for (EntityData sheet : data) {ExcelData excelData = new ExcelData();BeanUtils.copyProperties(sheet, excelData);excelDataList.add(excelData);}SimpleDateFormat slf = new SimpleDateFormat("yyyyMMddHHmmss");String time = slf.format(new Date());String fileName = String.format("数据导出%s.xlsx", time);String filePath = "";if (System.getProperty("os.name").toLowerCase().contains("mac")) {filePath = "/Users/admin/Downloads" + File.separator + fileName;} else {//配置服务器磁盘地址
//            filePath = "/home" + File.separator + "temp" + File.separator + fileName;}// 2、生成本地 excelEasyExcel.write(filePath, ExcelData.class).sheet("数据导出").doWrite(excelDataList);// 上传osstry (InputStream inputStream = new FileInputStream(new File(filePath))) {//TODO 调用上传服务} catch (Exception e) {throw new CustomException("长传导出异常");} finally {//删除临时文件try {org.apache.commons.io.FileUtils.forceDelete(new File(filePath));} catch (IOException e) {System.out.println("删除文件异常" + e);}}}
}

注意:本地测试需要先注释掉这段代码
try {
org.apache.commons.io.FileUtils.forceDelete(new File(filePath));
} catch (IOException e) {
System.out.println(“删除文件异常” + e);
}

七、配置线程池

这里用到了异步操作,需要配置线程池参数

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;import java.util.concurrent.ThreadPoolExecutor;@Configuration
public class ExecutorConfig {private static final int CORE_POOL_SIZE = 30;private static final int MAX_POOL_SIZE = CORE_POOL_SIZE * 2 + 1;@Bean(name="taskExecutor")public ThreadPoolTaskExecutor taskExecutor(){ThreadPoolTaskExecutor poolTaskExecutor = new ThreadPoolTaskExecutor();/*** 此方法返回可用处理器的虚拟机的最大数量; 不小于1* int core = Runtime.getRuntime().availableProcessors();*///设置核心线程数poolTaskExecutor.setCorePoolSize(CORE_POOL_SIZE);//设置最大线程数poolTaskExecutor.setMaxPoolSize(MAX_POOL_SIZE);//除核心线程外的线程存活时间poolTaskExecutor.setKeepAliveSeconds(3);//如果传入值大于0,底层队列使用的是LinkedBlockingQueue,否则默认使用SynchronousQueuepoolTaskExecutor.setQueueCapacity(40);//线程名称前缀poolTaskExecutor.setThreadNamePrefix("thread-execute");//设置拒绝策略poolTaskExecutor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());return poolTaskExecutor;}
}

八、配置环境参数

注意:换成自己redis的服务器地址
server.port=8888
spring.redis.database = 1
spring.redis.host = localhost
spring.redis.port = 6379
spring.redis.password =123456
spring.redis.jedis.pool.max-active = 8
spring.redis.jedis.pool.max-wait = -1ms
spring.redis.jedis.pool.min-idle = 0

九、测试类

1、启动项目
在这里插入图片描述

2、浏览器访问地址:http://localhost:8888/file/export
在这里插入图片描述

十、结果

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/122070.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

ActiveMQ消息中间件简介

一、ActiveMQ简介 ActiveMQ是Apache出品&#xff0c;最流行的&#xff0c;能力强劲的开源消息总线。ActiveMQ是一个完全支持JMS1.1和J2EE1.4规范的JMS Provide实现。尽管JMS规范出台已经是很久的事情了&#xff0c;但是JMS在当今的J2EE应用中仍然扮演这特殊的地位。 二、Active…

云计算模式的区域LIS系统源码,基于ASP.NET+JQuery、EasyUI+MVC技术架构开发

云计算模式的区域LIS系统源码 云LIS系统源码&#xff0c;自主版权 LIS系统是专为医院检验科的仪器设备能与计算机连接。可通过LIS系统向仪器发送指令&#xff0c;让仪器自动操作和接收仪器数据。并快速的将检验仪器中的数据导入到医生工作站中进行管理&#xff0c;且可将检验结…

springboot项目打jar包,运行时提示jar中没有主清单属性

可能性一&#xff1a; 没有在pom中加入maven插件 在pom中加入下方代码即可。 <build><plugins><plugin><groupId>org.apache.maven.plugins</groupId><artifactId>maven-compiler-plugin</artifactId><version>3.8.1</ve…

039-第三代软件开发-PDF阅读器

第三代软件开发-PDF阅读器 文章目录 第三代软件开发-PDF阅读器项目介绍PDF阅读器1 初始化PDF view2 qml 中使用3 创建模块 关键字&#xff1a; Qt、 Qml、 pdf、 LTDev、 本地 项目介绍 欢迎来到我们的 QML & C 项目&#xff01;这个项目结合了 QML&#xff08;Qt Met…

如何快速排查SSD IO延迟抖动问题?

一块固态硬盘设计背后&#xff0c;有硬件控制器&#xff0c;NAND闪存颗粒、DRAM&#xff0c;还有固件FTL算法等。SSD设计的本身其实是一件特别复杂的过程&#xff0c;需要考虑各种客户需求且要保证可靠性、性能、稳定性。 针对SSD的相关性能测试&#xff0c;SNIA也有专门针对SS…

【RabbitMQ 实战】12 镜像队列

一、镜像队列的概念 RabbitMQ的镜像队列是将消息副本存储在一组节点上&#xff0c;以提高可用性和可靠性。镜像队列将队列中的消息复制到一个或多个其他节点上&#xff0c;并使这些节点上的队列保持同步。当一个节点失败时&#xff0c;其他节点上的队列不受影响&#xff0c;因…

漏洞复现-showdoc文件上传_v2.8.3_(CNVD-2020-26585)

showdoc文件上传_v2.8.3_CNVD-2020-26585 漏洞信息 showdoc 2.8.3 以下版本中存在安全漏洞CNVD-2020-26585文件上传漏洞 描述 ShowDoc是一个非常适合IT团队的在线API文档、技术文档工具。通过showdoc&#xff0c;你可以方便地使用markdown语法来书写出美观的API文档、数据字…

java后端返回给前端不为空的属性

问题背景&#xff1a; 目前遇到的一个问题。一个对象里面定义了数组、集合、和字符串属性等&#xff0c;但是返回给前端的时候数组和集合都是空的&#xff0c;前端接收到的是“” 一个空字符。然后保存的时候又把空字符传给后端&#xff0c;出现了数据结构不匹配导致报错。 解…

Java8与JDK1.8与JDK8之间的关系是什么?

1.Java8等价于JDK8 2.JDK8或者JDK1.8是由于自从JDK1.5/JDK5命名方式改变后遗留的历史问题。所以JDK8或者JDK1.8是等价的。 2004年9月30日&#xff0c;J2SE1.5发布。为了表示该版本的重要性&#xff0c;J2SE 1.5更名为Java SE 5.0&#xff0c;从此开始&#xff0c;如下图像jav…

如何进行渗透测试以提高软件安全性?

对于各种规模的企业和组织来说&#xff0c;软件安全是一个至关重要的问题。随着网络攻击越来越复杂&#xff0c;软件中的漏洞越来越多&#xff0c;确保你的软件安全比以往任何时候都更重要。提高软件安全性的一个有效方法是渗透测试&#xff08;penetration testing&#xff09…

雨云游戏云面板服使用教程我的世界Forge服务端开服教程(翼龙面板)

雨云面板服目前支持一键开服的游戏有&#xff1a;Minecraft Java版、Minecraft 基岩版、泰拉瑞亚、饥荒&#xff0c;还提供纯Java/Linux环境&#xff08;Docker&#xff09;&#xff0c;方便开自己开其他游戏服。 其中Minecraft Java版支持一键开服的有Arclight、Mohist、CatS…

环形链表 II

一、题目描述 题目链接&#xff1a;力扣&#xff08;LeetCode&#xff09;官网 - 全球极客挚爱的技术成长平台 二、题解 对于本题&#xff0c;我们可以得到以下结论&#xff1a; 让一个指针从链表起始位置开始遍历链表&#xff0c;同时让一个指针从判环时相遇点的位置开始绕…

原始流,缓冲流性能比较

一.低级字节流一个一个字节复制 1.代码 package org.example;import java.io.*;public class day13 {//原视频路径private static final String file1 "D:\\temp\\day05\\改名.mp4";//目的视频路径private static final String file2 "D:\\temp\\day05\\不改…

windows下OOM排查

如下有一段代码 package com.lm.demo.arthas.controller;import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController;import java.util.A…

C++学习day--24 推箱子游戏图像化开发

环境要求&#xff1a; 1、VS2015以上 2、成功安装并配置图形库 项目注意事项&#xff1a;代码复制好以后&#xff0c;把下面的字符集改为多字节字符集 第 1 节 项目需求 实现一款推箱子游戏&#xff0c;效果如下图所示 , 具体规则&#xff1a; 1. 箱子只能推动而不能拉动…

ROS笔记之visualization_msgs-Marker学习

ROS笔记之visualization_msgs-Marker学习 code review! 文章目录 ROS笔记之visualization_msgs-Marker学习一.line_strip例程二.line_list例程一二.line_list例程二二.TEXT_VIEW_FACING例程三.附CMakeLists.txt和package.xml五.关于odom、base_link和map坐标系六.关于visualiz…

TCP / UDP 概念 + 实验(计网自顶向下)

Github源码 moranzcw/Computer-Networking-A-Top-Down-Approach-NOTES: 《计算机网络&#xff0d;自顶向下方法(原书第6版)》编程作业&#xff0c;Wireshark实验文档的翻译和解答。 (github.com) 暂定打算分2步走&#xff0c;前置是中科大对应计网黑书的视频 第1步完成14个Wire…

设置Ubuntu 20.04的静态IP地址(wifi模式下)

一、引言 自己家用的Ubuntu的&#xff0c;重启后ip地址经常会改变&#xff0c;这个时候就需要我们手动配置静态IP了。 二、优点 给Ubuntu设置一个静态IP地址有以下几个好处&#xff1a; 持久性&#xff1a;静态IP地址是固定不变的&#xff0c;与设备的MAC地址绑定。这意味着…

【广州华锐视点】VR飞行员驾驶模拟实训系统

VR飞行员驾驶模拟实训系统是一种基于虚拟现实技术的航空装备仿真测试技术&#xff0c;可以用于飞行员、乘务员和机务人员的训练。该系统可以模拟真实的飞行环境&#xff0c;包括天气、地形、飞机性能等&#xff0c;使被试者能够在虚拟环境中进行飞行操作&#xff0c;从而提高其…

SSH安全登录远程主机

SSH服务器简介 SSH即Security SHell的意思&#xff0c;它可以将连线的封包进行加密技术&#xff0c;之后进行传输&#xff0c;因此相当的安全。 SSH是一种协议标准&#xff0c;其目的是实现安全远程登录以及其它安全网络服务。 SSH协定&#xff0c;在预设的状态下&#xff0c;…