通用导出功能-实现思路
实现思路:
AOP 环绕通知,通过注解@ExcelExport
来注释一个查询接口,通过环绕通知处理这个查询接口。
@Around("@annotation(excelExport)")
public Object excelExport(ProceedingJoinPoint joinPoint, ExcelExport excelExport) throws Throwable {
// ...
}
异步时候将任务处理成一个线程任务,并将任务绑定一个uuid,放在一个 ConcurrentHashMap
中,key
是uuid
,value
是Future
任务本身。
private Map<String, Future> futureMap = new ConcurrentHashMap();
// ...
private String asyncExecute(ExportDataHelper.ExportTask exportTask) {
if (this.exportAsyncTemplate == null) {
// ...
} else {
UUID uuid = UUID.randomUUID();
exportTask.getDto().setTaskCode(uuid.toString());
return this.exportAsyncTemplate.submit(exportTask.getDto(), () -> {
Future future = this.executorService.submit(exportTask);
log.info(uuid + "导出参数:" + getArgs(exportTask.args) + "导出方法:" + exportTask.method.getName());
this.futureManager.put(uuid, future);
return uuid.toString();
});
}
}
提供统一的查询接口,查看任务进行状态,并且通过userid
关联任务,保证在操作随机导出任务时,只有创建人可以取消自己创建的导出任务。
取消任务,需要先核对当前角色是否为对应任务的创建人,之后调用取消方法。取消方法中会尝试根据uuid
找到上述futureMap
中的线程任务,之后尝试通过java.util.concurrent.Future#cancel
方法取消异步任务,并返回取消结果。
public TaskState cancel(String uuid) {
Future future = (Future)this.futureMap.remove(uuid);
if (future == null) {
LOGGER.warn("未找到该导出任务[" + uuid + "]");
return ExportFutureManager.TaskState.REMOVED;
} else if (future.isCancelled()) {
LOGGER.warn("该导出任务[" + uuid + "]已取消");
return ExportFutureManager.TaskState.CANCELED;
} else if (future.isDone()) {
LOGGER.warn("该导出任务[" + uuid + "]已完成");
return ExportFutureManager.TaskState.DONE;
} else {
return future.cancel(true) ? ExportFutureManager.TaskState.SUCCESS : ExportFutureManager.TaskState.FAILED;
}
}
存在问题:
由于整个过程中,对任务的记录只存在于内存中的ConcurrentHashMap
中,当服务异常宕机时,会丢失全部任务。此时会造成mysql
中的任务记录与实际任务记录不一致,需要人为干预。
设计初,考虑导出数据本身相对并不重要,可以人为手动重新导出,此实现为平衡业务需求与系统复杂度的结果。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· Docker 太简单,K8s 太复杂?w7panel 让容器管理更轻松!