导入导出事件开发参考指南
导入导出事件开发参考指南
该中间件,统一实现文件导入,导出的任务进度监控。用于业务中涉及文件的导入导出,
并且需要异步导入导出时接入(同步任务需返回特定结果的无法接入)。注:该中间件仅实现任务侧的功能。导出文件的生成,上传文件至缓存服务;导入数据的解析,导入需各自业务自行实现。
前置条件
<dependencies> 下新增如下依赖
<dependencie>
<groupId>cn.com.lightcode.cloud</groupId>
<artifactId>lightcode-cloud</artifactId>
<version>2.0</version>
</dependencie>- 需能访问公司内网环境,访问maven私服。
- 微服务环境,能够通过feign调用file-server服务。
使用方式教程
- 流程说明
当业务需要接入导入导出任务时,首先创建导入导出任务,拿到中间件返回的任务id,用于后续插入任务日志。
并将该任务id反馈给前端,以便前端能够获取导出导入任务详情。任务创建成功后,拿着中间件返回的任务id,在各业务自行控制的逻辑中,以插入日志的方式向中间件反馈任务状态,
任务文件等信息。
- 时序图

步骤一、创建导入导出任务
1、首先,需要准备一个feign远程调用接口,在feign的API文件中建立新建任务远程调用接口方法,代码如下:
@FeignClient(value = "file-server",configuration = FeignConfig.class)
public interface FileServerFeignImpl {
/**
* 新建导入导出任务
* @param task 任务实体
* @return
*/
@PostMapping("/uploadTaskInfo/")
JsonResult createUploadTask(@RequestBody UploadTaskInfo task);
}注:此接口存在时间限制,同一任务编码的任务在规定时间内无法创建,当遇到此问题时,接口返回结果的msg中会有体现,
等时间阈值过去后,便可再次创建。
- 接口说明
接口地址:/uploadTaskInfo/
请求方式:POST
请求参数:UploadTaskInfo 实体中
| 参数名称 | 数据类型 | 是否必须 | 参数说明 |
|---|---|---|---|
| taskCode | String | 是 | 任务编码(业务自己生成, 保证唯一性, 防止数据错误) |
| createBy | Long | 是 | 任务创建者id |
| taskName | String | 是 | 任务名称 |
- 请求示例
{
"taskCode": "CE_SHI_REN_WU",
"createBy": 1,
"taskName": "接口测试任务"
}
- 返回结果:
jsonResult.getCode == 0 代表创建任务成功jsonResult.getData 返回的是任务实例id
| 参数名称 | 数据类型 | 是否必须 | 参数说明 |
|---|---|---|---|
| 无 | Long | 是 | 任务实例id |
- 返回示例
{
"code": 0,
"msg": "操作成功",
"data": 1,
"ok": true
}- 代码示例
@Service
@Slf4j
public class IndisciplineInfoServiceImpl extends BaseCustomServiceImpl<IndisciplineInfoMapper, IndisciplineInfo> implements IndisciplineInfoService {
/**
* 导出
*
* @param queryDto
*/
@Override
public JsonResult exportExcel(IndisciplineInfoDTO queryDto, HttpServletResponse response) {
try {
// 创建导出任务实体
UploadTaskInfo uploadTaskInfo = new UploadTaskInfo();
// 设置任务编码(保证业务模块的任务编码唯一性)
uploadTaskInfo.setTaskCode(DORM_EXPORT_INDISCIPLINE);
uploadTaskInfo.setTaskName("宿舍违纪导出任务");
// feign远程调用创建任务
JsonResult result = fileFeginService.createUploadTask(uploadTaskInfo);
if (result.isOK() && result.getData() != null) {
// 请求成功获取任务实例id
Long progressId = Long.valueOf(result.getData().toString());
// 异步进行导出逻辑
executeExport(queryDto, response, progressId);
// 给前端返回任务实例id
return result;
} else {
log.error("[宿舍违纪] 生成导出任务失败,调用远程中间件接口未返回进度编号,返回信息{}", result.toString());
throw new BusinessException("生成导出任务失败");
}
} catch (BusinessException e) {
throw e;
} catch (Exception e) {
log.error("[宿舍违纪]: 导出数据失败,原因[{}]", e.getMessage());
throw new BusinessException("导出失败,请联系管理员");
}
}
}步骤二、插入任务日志记录
1、在feign的API文件中建立远程调用接口
@FeignClient(value = "file-server",configuration = FeignConfig.class)
public interface FileServerFeignImpl {
/**
* 插入任务日志记录
*
* @param logInfo 日志实体
* @return
*/
@PostMapping("/uploadLogInfo/insertLog")
JsonResult insertLog(@RequestBody UploadLogInfoDTO logInfo);
}注:在此接口中,可以插入任务进度信息
taskProgress(0-100)用于控制任务进度。在任务完成时可以插入taskState为2的数据,
用于结束任务。当有文件时,可以带入参数fileInfos
filePath参数来自于文件上传成功后的文件id与下载地址拼接例如: /student-work-service/leaveCommon/fileDownload/1
/student-work-service/leaveCommon/fileDownload/1为下载地址
1为文件上传后提供的文件id
- 接口说明
接口地址: /uploadLogInfo/insertLog
请求方式:POST
请求参数:UploadLogInfoDTO 实体中
| 参数名称 | 数据类型 | 是否必须 | 参数说明 |
|---|---|---|---|
| taskId | Long | 是 | 任务实例id(新建任务时返回的实例id) |
| logMessage | String | 是 | 日志信息(需要填入的对应日志信息) |
| taskProgress | Integer | 是 | 进度信息(业务生成任务对应的进度; 范围1-100) |
| taskState | Integer | 否 | 任务状态(0: 未开始; 1: 进行中; 2: 已完成; 3: 已取消) |
| fileInfos | List | 否 | 文件信息集 |
taskState------说明:当需要改变任务状态时, 可以携带此参数改变任务状态(注:取消任务时,不需要回调可以用此方法取消任务)
fileInfos--------说明:当需要关联任务文件时, 即可传入该参数
| 参数名称 | 数据类型 | 是否必须 | 参数说明 |
|---|---|---|---|
| filePath | String | 是 | 文件路径(文件上传成功后的文件路径) |
| fileSize | String | 是 | 文件大小 |
| fileName | String | 否 | 文件名称 |
- 请求示例
{
"taskId": 1,
"logMessage": "任务完成",
"taskProgress": 100,
"taskState": 2,
"fileInfos": [
{
"fileName": "测试表格文件.xlsx",
"fileSize": "1MB",
"filePath": "/student-work-service/leaveCommon/fileDownload/1"
},
{
"fileName": "测试压缩文件.zip",
"fileSize": "100MB",
"filePath": "/student-work-service/leaveCommon/fileDownload/2"
}
]
}
- 返回结果: jsonResult.getCode == 0 代表日志插入成功
- 返回示例
{
"code": 0,
"msg": "操作成功",
"ok": true
}步骤三、上传文件到缓存服务
1、在feign的API文件中建立远程调用接口
@FeignClient(value = "student-work-service",configuration = FeignConfig.class)
public interface studentWorkServiceFeignImpl {
/**
* 上传缓存文件
* @param file 文件
* @return
*/
@PostMapping(value = "/fileMongo/uploadFile",consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
JsonResult uploadFile(@RequestPart("file") MultipartFile file);
}- 接口说明
接口地址: /fileMongo/uploadFile
请求方式:POST
请求参数:file
| 参数名称 | 数据类型 | 是否必须 | 参数说明 |
|---|---|---|---|
| file | MultipartFile | 是 | 文件 |
- 返回结果: jsonResult.getCode == 0 代表文件上传成功
| 参数名称 | 数据类型 | 是否必须 | 参数说明 |
|---|---|---|---|
| id | String | 是 | 上传文件的id |
- 返回示例
{
"code": 0,
"msg": "操作成功",
"data": {
"id": "62f365cd39b65353b3513af5",
"fileName": "测试文件上传-2022-08-05.xlsx",
"fileSize": 3654,
"uploadDate": "2022-08-10 16:01:17",
"md5": "f3f13f26eb79ac3d35698e159a011f85",
"content": {
"type": 0,
"data": "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"
},
"contentType": "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
"suffix": ".xlsx"
},
"ok": true
}- 示例代码
@Service
@Slf4j
public class CommonServiceImpl implements CommonService {
@Resource
@Lazy
private StudentWorkFeignService studentWorkFeignService;
/**
* 上传mongo文件
* @param file 文件
* @return 上传成功后的文件id
*/
@Override
public String saveMongodb(File file) throws Exception {
InputStream inputStream = new FileInputStream(file);
MultipartFile tempFile = new MockMultipartFile(file.getName(), file.getName(), "text/plan", inputStream);
JsonResult jsonResult = studentWorkFeignService.uploadFile(tempFile);
Map<String, Object> data = (Map<String, Object>) jsonResult.getData();
return data.get("id").toString();
}
}辅助接口说明
一、查询任务状态信息
1、在feign的API文件中建立远程调用接口
@FeignClient(value = "file-server",configuration = FeignConfig.class)
public interface FileServerFeignImpl {
/**
* 查询任务状态信息
*
* @param taskId 任务id
* @return
*/
@GetMapping("/uploadTaskInfo/getStateById")
JsonResult getStateById(@RequestParam("taskId") Long taskId);
}- 接口说明
接口地址: /uploadTaskInfo/getStateById
请求方式:GET
请求参数:taskId
| 参数名称 | 数据类型 | 是否必须 | 参数说明 |
|---|---|---|---|
| taskId | Long | 是 | 任务实例id(新建任务时返回的实例id) |
- 返回结果
jsonResult.getCode == 0 代表请求成功
jsonResult.getData 返回的是任务实例状态
| 参数名称 | 数据类型 | 是否必须 | 参数说明 |
|---|---|---|---|
| 无 | Integer | 是 | 任务状态(0: 未开始; 1: 进行中; 2: 已完成; 3: 已取消) |
- 自行查询方式
REDIS的缓存键值前缀为:UPLOAD_TASK_STATE:
可自行拼接任务实例id从redis中获取任务状态,缓存的为任务状态码,与接口返回状态码一致
注:redis中的缓存有效时长为最新一次更新状态后的1小时,过期后无法查询到状态,仍然需要任务状态请走接口查询
二、查询任务相关联文件
1、在feign的API文件中建立远程调用接口
@FeignClient(value = "file-server",configuration = FeignConfig.class)
public interface FileServerFeignImpl {
/**
* 查询任务文件
*
* @param taskId 任务id
* @param fileType 文件类型(非必须)
* @param fileSize 文件大小(非必须)
* @return
*/
@GetMapping("/uploadTaskFile/list")
JsonResult getFileList(@RequestParam("taskId") Long taskId,@RequestParam("fileType") String fileType,@RequestParam("fileSize") String fileSize);
}- 接口说明
接口地址: /uploadTaskFile/list
请求方式:GET
请求参数:taskId, fileType, fileSize
| 参数名称 | 数据类型 | 是否必须 | 参数说明 |
|---|---|---|---|
| taskId | Long | 是 | 任务实例id(新建任务时返回的实例id) |
| fileType | String | 否 | 文件类型(例如:xls, xlsx, pdf, jgp...) |
| fileSize | String | 否 | 文件大小 |
- 返回结果
jsonResult.getCode == 0 代表请求成功
jsonResult.getData 返回的是任务关联文件集-LIST集合
| 参数名称 | 数据类型 | 是否必须 | 参数说明 |
|---|---|---|---|
| filePath | String | 是 | 文件路径 |
| fileType | String | 是 | 文件类型(例如:xls, xlsx, pdf, jgp...) |
| fileSize | String | 是 | 文件大小 |
三、查询任务日志
1、在feign的API文件中建立远程调用接口
@FeignClient(value = "file-server",configuration = FeignConfig.class)
public interface FileServerFeignImpl {
/**
* 查询任务日志记录
*
* @param taskId 任务id
* @return
*/
@GetMapping("/uploadLogInfo/list")
JsonResult getLogList(@RequestParam("taskId") Long taskId);
}- 接口说明
接口地址: /uploadLogInfo/list
请求方式:GET
请求参数:taskId
| 参数名称 | 数据类型 | 是否必须 | 参数说明 |
|---|---|---|---|
| taskId | Long | 是 | 任务实例id(新建任务时返回的实例id) |
- 返回结果
jsonResult.getCode == 0 代表请求成功
jsonResult.getData 返回的是日志集-LIST集合
| 参数名称 | 数据类型 | 是否必须 | 参数说明 |
|---|---|---|---|
| logMessage | String | 是 | 日志信息 |
| taskProgress | Integer | 是 | 任务进度信息(0-100) |
| createTime | Date | 是 | 日志插入时间 |
| taskId | Long | 是 | 任务id |
过程示例代码(注: 此处的@Async异步注解未生效, 异步需将异步方法提出当前类)
一、导入任务
@Service
@Slf4j
public class HouseManagerServiceImpl extends BaseCustomServiceImpl<HouseManagerMapper, HouseManager> implements HouseManagerService {
/**
* 导入
*
* @param file
* @return
*/
@Override
@Transactional(rollbackFor = Exception.class)
public JsonResult importExel(MultipartFile file) {
try {
UploadTaskInfo uploadTaskInfo = new UploadTaskInfo();
uploadTaskInfo.setTaskCode(DORM_EXPORT_HOUSE_MANAGER);
uploadTaskInfo.setTaskName("宿管管理导入任务");
JsonResult result = fileFeginService.createUploadTask(uploadTaskInfo);
if (result.isOK() && result.getData() != null) {
Long progressId = Long.valueOf(result.getData().toString());
executeImport(progressId, file);
return result;
} else {
log.error("[宿管管理] 生成导入任务失败,调用远程中间件接口未返回进度编号,返回信息{}", result.toString());
throw new BusinessException("生成导入任务失败");
}
} catch (BusinessException e) {
throw e;
} catch (Exception e) {
log.error("[宿管管理]: 导入数据失败,原因[{}]", e.getMessage());
throw new BusinessException("导入失败,请联系管理员");
}
}
@Async
public void executeImport(Long progressId, MultipartFile file) {
// 校验文件类型
occupancyService.checkFileType(file);
commonService.executeLog(progressId, "文件校验通过", 10, 1, null);
try {
HashMap<String, String> headerAlias = new HashMap<>(5);
headerAlias.put("姓名", "username");
headerAlias.put("工号", "workNo");
headerAlias.put("电话", "telephone");
headerAlias.put("管理类型(楼栋/单元)", "managerType");
headerAlias.put("管理范围(楼栋/单元编号)", "managerScope");
// hutool从0开始计算行数
List<ManageExcelDto> list = ExcelUtils.imports(file, headerAlias, ManageExcelDto.class, 0, 1);
commonService.executeLog(progressId, "文件读取完成", 30, 1, null);
List<HouseManager> houseManagers = checkCanImport(list);
commonService.executeLog(progressId, "文件解析完成", 50, 1, null);
commonService.executeLog(progressId, "数据校验通过", 90, 1, null);
for (HouseManager houseManager : houseManagers) {
createOrUpdateManager(null, houseManager, 2);
}
commonService.executeLog(progressId, "数据导入完成", 100, 2, null);
} catch (BusinessException e) {
throw e;
} catch (Exception e) {
log.error("[宿管管理] 导入宿舍信息失败,原因:[{}]", e.getMessage());
throw new BusinessException("导入宿舍信息失败,请联系管理员!");
}
}
}二、导出任务
@Service
@Slf4j
public class IndisciplineInfoServiceImpl extends BaseCustomServiceImpl<IndisciplineInfoMapper, IndisciplineInfo> implements IndisciplineInfoService {
/**
* 导出
*
* @param queryDto
*/
@Override
public JsonResult exportExcel(IndisciplineInfoDTO queryDto, HttpServletResponse response) {
try {
UploadTaskInfo uploadTaskInfo = new UploadTaskInfo();
uploadTaskInfo.setTaskCode(DORM_EXPORT_INDISCIPLINE);
uploadTaskInfo.setTaskName("宿舍违纪导出任务");
JsonResult result = fileFeginService.createUploadTask(uploadTaskInfo);
if (result.isOK() && result.getData() != null) {
Long progressId = Long.valueOf(result.getData().toString());
executeExport(queryDto, response, progressId);
return result;
} else {
log.error("[宿舍违纪]生成导出任务失败,调用远程中间件接口未返回进度编号,返回信息{}", result.toString());
throw new BusinessException("生成导出任务失败");
}
} catch (BusinessException e) {
throw e;
} catch (Exception e) {
log.error("[宿舍违纪]: 导出数据失败,原因[{}]", e.getMessage());
throw new BusinessException("导出失败,请联系管理员");
}
}
@Async
public void executeExport(IndisciplineInfoDTO queryDto, HttpServletResponse response, Long progressId) {
try {
List<IndisciplineInfoExcelVo> list = indisciplineInfoMapper.getExcelList(queryDto);
commonService.executeLog(progressId, "查询导出数据成功,共 " + list.size() + " 条", 10, 1, null);
HashMap<String, String> headerAlias = new HashMap<>(12);
headerAlias.put("username", "姓名");
headerAlias.put("studentId", "学号");
headerAlias.put("sex", "性别");
headerAlias.put("college", "学院");
headerAlias.put("major", "专业");
headerAlias.put("grade", "年级");
headerAlias.put("classes", "班级");
headerAlias.put("studentType", "学生类型");
headerAlias.put("dormitoryId", "宿舍号");
headerAlias.put("disciplineTypeValue", "违纪类型");
headerAlias.put("disciplineDate", "违纪日期");
headerAlias.put("disciplineInfo", "违纪情节");
// 导出文件
if (!queryDto.getExportType().equals("1")) {
ExcelUtils.export(list, headerAlias, response, "宿舍违纪信息表");
return;
}
TreeMap<String, String> treeMap = new TreeMap<>();
treeMap.putAll(headerAlias);
// 第一步、生成根路径
StringBuffer exportRootPath = new StringBuffer(FileUtil.getTmpDirPath()).append(File.separator).append(UUID.randomUUID().toString()).append(File.separator)
.append("宿舍违纪" + DateUtil.date());
if (!FileUtil.exist(exportRootPath.toString())) {
FileUtil.mkdir(exportRootPath.toString());
}
// 生成临时文件
File file = new File(String.valueOf(exportRootPath) + File.separator + "宿舍违纪信息表" + "-" + DateUtil.today() + ".xlsx");
commonService.executeLog(progressId, "生成缓存临时文件成功..", 30, 1, null);
ExcelUtils.export(list, treeMap, file);
commonService.executeLog(progressId, "写入临时文件成功...", 80, 1, null);
// 将临时文件上传至缓存服务,并拿到对应的上传文件id
String mongoFileId = commonService.saveMongodb(file);
commonService.executeLog(progressId, "上传数据文件至缓存服务成功..", 95, 1, null);
LogFileDTO logFileDTO = new LogFileDTO();
logFileDTO.setFileName(file.getName());
logFileDTO.setFileSize(CommonUtil.getFileSize(file));
// 拼接上传文件下载路径
logFileDTO.setFilePath("/student-work-service/leaveCommon/fileDownload/" + mongoFileId);
// 插入任务完成日志
commonService.executeLog(progressId, "导出成功..", 100, 2, logFileDTO);
} catch (BusinessException e) {
throw e;
} catch (Exception e) {
log.error("[宿舍违纪]: 导出数据失败,原因[{}]", e.getMessage());
throw new BusinessException("导出失败,请联系管理员");
}
}
}