# :-: 数据导出
一、总体流程如下
数据导出采用异步任务方式处理。用户先在页面点击导出数据按钮执行创建一个导出任务,专门的任务对其执行具体的导出任务。执行完毕后会生成一个csv文件存储在OSS。用户去下载中心可以查看并下载文件
![](https://img.kancloud.cn/de/c9/dec931e2d0387f40b2c78d126c639741_1267x158.png)
二、流程说明
1、创建任务:
A:准备好导出sql模板语句 放在common\_query\_template 表。需要符合mybatis 标准
B:页面执行点击导出操作,请求接口/data/export 参数包含 导出名称 导出数据列 查询条件 模板SQL的keyCode等。
C:接口将导出的请求验证之后存储在common\_export 表。
~~~
CommonQueryTemplate queryTemplate = queryService.getCommonQueryTemplate(request.getExportKey());
AssertUtil.notNull(queryTemplate, "参数有误!");
CommonExport commonExport=new CommonExport();
commonExport.setExportKey(request.getExportKey());
commonExport.setExportName(request.getExportName());
commonExport.setQueue(JSONObject.toJSONString(request));
commonExport.setUserId(AdminContextUtil.getMyId());
commonExport.setStatus(0);
int r=commonExportMapper.insert(commonExport);
~~~
2、发送MQ消息:
创建任务后系统发送一个MQ消息 消息的内容是导出任务表的ID
~~~
kafkaSender.sendMsg(MsgConf.Topics.Export,commonExport.getId());
~~~
3、消费MQ消息:
导出的Topic接收到消息之后执行导出的任务
~~~
@Component
@Slf4j
public class ExportListener {
@Resource ExportService exportService;
@KafkaListener(id="Export",topics = "Export" )
public void onMessage0( ConsumerRecord r){
log.info("【ExportListener消息消费接收到消息key....{}.....value....{}",r.key(),r.value());
Object value=r.value().toString();
exportService.export(Long.parseLong(value.toString()));
}
}
~~~
根据导出任务的条件执行模板SQL语句。然后将查询到的数据存储在csv 文件中。将生成的csv文件存放到阿里云的OSS中。导出任务完成。
~~~
/**
* 导出数据
*/
public void export(Long id){
CommonExport commonExportUpdate=new CommonExport();
commonExportUpdate.setId(id);
QuerySQLContext.remove();
try {
log.info("【导出数据】.....id{}",id);
CommonExport commonExport = commonExportMapper.selectById(id);
AssertUtil.isTrue(commonExport!=null, "数据导出失败");
if (commonExport.getStatus()==1) {
log.error("【导出数据】数据正在导出......停止本次导出");
return;
}
if (commonExport.getStatus() == 2) {
log.error("【导出数据】数据导出失败......停止本次导出");
return;
}
log.info("【导出数据】....commonExport.....{}",commonExport);
CommonQueryTemplate queryTemplate = queryService.getCommonQueryTemplate(commonExport.getExportKey());
AssertUtil.notNull(queryTemplate, "【导出数据】queryTemplate==null");
ExportDataReq exportDataReq = JSONObject.parseObject(commonExport.getQueue(),ExportDataReq.class);
QuerySQLContext.set(getQuerySqlTemplate(queryTemplate));
String fileName ="export/" + commonExport.getExportName().concat(".csv");
commonExportUpdate.setStatus(1);
commonExportMapper.updateById(commonExportUpdate);
exportData(exportDataReq, commonExport, fileName, 0L);
commonExportUpdate.setStatus(2);
commonExportUpdate.setUrl(ConfUtil.serverFileUrl+fileName);
commonExportMapper.updateById(commonExportUpdate);
}catch (Exception e){
log.error("【导出数据】........发生异常......{}",e);
if (commonExportUpdate.getId() != null) {
commonExportUpdate.setErrorDesc(e.getMessage());
commonExportUpdate.setStatus( 3);
commonExportMapper.updateById(commonExportUpdate);
}
e.printStackTrace();
}
}
/**
* 数据导出执行
*/
private void exportData(ExportDataReq exportDataReq ,CommonExport data, String fileName,Long nextPoint) {
JSONObject search = exportDataReq.getSearchParam();
search.put(TemplateKit.PAGE_SIZE, 1000);
List<Map> expDataList =ObjectUtils.defaultIfNull(queryService.queryExportData(search),new ArrayList<>());
ExcelDataUtils.ExcelHeaderData excelHeaderData =
ExcelDataUtils.builderHeaderAndData(exportDataReq.getExportColumn().stream()
.map(ExportDataReq.Column::getKey).collect(Collectors.toList()),
exportDataReq.getExportColumn().stream()
.map(ExportDataReq.Column::getValue).collect(Collectors.toList()), expDataList);
File file = new File("export_" + data.getExportName() + ".csv");
List<String[]> arrayList = new ArrayList<>();
if (nextPoint <= 0) {
arrayList.add(excelHeaderData.getHeader());
}
arrayList.addAll(excelHeaderData.getData());
CsvUtil.write(file, arrayList);
data.setTotal(ObjectUtils.defaultIfNull(data.getTotal(), 0L) + expDataList.size());
log.info("【数据导出执行】:{},total:{},dataSize:{}", fileName, data.getTotal(), excelHeaderData.getData().size());
if (excelHeaderData.getData().size() > 0) {
search.put(TemplateKit.PAGE_NUMBER, ObjectUtils.defaultIfNull(search.getLong(TemplateKit.PAGE_NUMBER), 0L) + 1);
nextPoint = OSSClientUtil.appendUpload(fileName, file, nextPoint);
exportData(exportDataReq, data, fileName, nextPoint);
}
}
~~~
4、导出文件下载
导出的任务完成之后会将下载文件的URL写入common\_export 表。下载中心下载相应的数据
![](https://img.kancloud.cn/ef/00/ef00796d756c2db62701104b08aa1003_1525x1071.png)
- 项目介绍
- 项目声明
- 项目简介
- 架构设计
- 项目亮点功能介绍
- 技术栈介绍
- 核心功能
- 运行环境
- 项目更新日志
- 文档更新日志
- F&Q
- 部署教程
- 环境准备
- JDK安装
- JDK1.8,17共存
- maven
- 分布式缓存Redis
- 单机版
- 集群
- 注册&配置中心alibaba/nacos
- 介绍
- Nacos安装
- Nacos配置中心
- Nacos注册发现
- Nacos生产部署方案
- 服务监控-BootAdmin
- 基本介绍
- 如何使用
- 整合Admin-Ui
- 客户端配置
- 链路追踪
- 基本介绍
- SkyWalking-1
- Skywalking-1
- 消息队列
- Kafka
- docker安装kafka
- Linux集群
- Maven私服
- nexus安装部署
- nexus使用介绍
- 全文搜索elasticsearch
- windows集群搭建
- docker安装es
- ElasticHD
- linux集群部署
- 统一日志解决方案
- 日志解决方案设计
- 介绍与相关资料
- ELK安装部署
- elasticsearch 7.5
- logstash-7.5
- kibana-7.5
- filebeat
- 服务监控-Prometheus
- Prometheus安装配置
- Prometheus介绍
- grafana
- 持续集成部署CICD
- 自动化部署Jenkins
- 安装部署win
- 打包发布远程执行
- 安装部署linux
- jenkins+gitlab+docker容器化工程自动化部署
- Git
- CICD说明
- 阿里云效
- CentOS_MYSQL安装
- docker
- 安装
- Docker安装Nginx
- Docker部署启动springboot
- dockerCompose
- harbor
- Docker私有镜像仓库
- Portainer
- Docker远程连接设置
- 打包工程
- 必要启动模块
- 核心模块
- 登录认证
- 缓存功能
- 日志模块
- 分布式锁
- 消息队列
- 异常处理
- 系统接口
- 参数验证
- es检索
- 数据导出
- 系统设计
- 系统总体架构
- 扩展模块(可选)
- 限流熔断alibaba/sentinel
- 使用Sentinel实现gateway网关及服务接口限流
- Sentinel使用Nacos存储规则及同步
- 服务调用Feign
- Feign基本介绍
- 如何使用
- 负载均衡
- 请求超时
- 请求拦截器
- 分布式任务调度
- XXL-JOB
- 分布式事务
- TX-LCN
- Seata
- Seata原理解析
- 数据库分库分表
- swagger文档
- 分布式ID生成器解决方案
- 服务网关CloudGateway
- 基本介绍
- 使用网关
- 路由配置
- 全局过滤器
- 服务认证授权架构设计
- 认证服务流程
- 授权服务流程
- 系统幂等性设计与实践
- 分布式日志链路跟踪
- 实时搜索系统设计
- 应用性能
- 压力测试工具
- Apache JMeter介绍和安装
- ApacheJMeter使用
- JVM
- JVM性能调优
- 常见JVM内存错误及解决方案
- JVM 分析工具详解
- Spring Cloud性能调优
- Linux运维
- Linux 常用命令
- Linux开启端口