通用导出功能-实现思路

实现思路:

AOP 环绕通知,通过注解@ExcelExport来注释一个查询接口,通过环绕通知处理这个查询接口。

@Around("@annotation(excelExport)")
public Object excelExport(ProceedingJoinPoint joinPoint, ExcelExport excelExport) throws Throwable {
  // ...
}

异步时候将任务处理成一个线程任务,并将任务绑定一个uuid,放在一个 ConcurrentHashMap 中,keyuuidvalueFuture 任务本身。

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中的任务记录与实际任务记录不一致,需要人为干预。

设计初,考虑导出数据本身相对并不重要,可以人为手动重新导出,此实现为平衡业务需求与系统复杂度的结果。

posted @ 2023-07-10 14:51  萝卜不会抛异常  阅读(23)  评论(0编辑  收藏  举报