# :-: 數據導出
一、總體流程如下
數據導出采用異步任務方式處理。用戶先在頁面點擊導出數據按鈕執行創建一個導出任務,專門的任務對其執行具體的導出任務。執行完畢后會生成一個csv文件存儲在OSS。用戶去下載中心可以查看并下載文件

二、流程說明
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 表。下載中心下載相應的數據

- 項目介紹
- 項目聲明
- 項目簡介
- 架構設計
- 項目亮點功能介紹
- 技術棧介紹
- 核心功能
- 運行環境
- 項目更新日志
- 文檔更新日志
- 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開啟端口