Excel高性能异步导出完整方案!

前言

在大型电商系统中,数据导出是一个高频且重要的功能需求。

传统的同步导出方式在面对大数据量时往往会导致请求超时、内存溢出等问题,严重影响用户体验。

苏三商城项目创新性地设计并实现了一套完整的Excel异步导出机制,通过注解驱动、任务队列、定时调度、消息通知等技术手段,完美解决了大数据量导出的技术难题,成为项目的重要技术亮点。

最近准备面试的小伙伴,可以看一下这个宝藏网站(Java突击队):www.susan.net.cn,里面:面试八股文、场景设计题、面试真题、7个项目实战、工作内推什么都有

系统架构设计

整体架构图

核心组件说明

  1. 注解驱动层 :通过@ExcelExport注解实现声明式编程
  2. 切面处理层CommonTaskAspect负责拦截和任务创建
  3. 任务管理层ExcelExportTask执行具体的导出逻辑
  4. 调度引擎层:基于Quartz的定时任务调度
  5. 消息通知层:RocketMQ + WebSocket实现异步通知
  6. 存储层:MySQL存储任务状态,OSS存储导出文件

异步导出流程详解

完整流程图

关键步骤分析

1. 注解驱动任务创建

java 复制代码
@ExcelExport(ExcelBizTypeEnum.USER)
@ApiOperation(notes = "导出用户数据", value = "导出用户数据")
@PostMapping("/export")
public void export(HttpServletResponse response, UserConditionEntity userConditionEntity) {
    // 方法体可以为空,切面会自动处理
}

设计亮点

  • 声明式编程:通过注解实现功能声明,代码简洁
  • 零侵入性:业务方法无需修改,切面自动处理
  • 类型安全:通过枚举确保业务类型的正确性

2. 切面拦截与任务创建

java 复制代码
@Aspect
@Component
public class CommonTaskAspect {
    
    @Before("@annotation(cn.net.susan.annotation.ExcelExport)")
    public void before(JoinPoint joinPoint) throws Throwable {
        // 获取注解信息
        ExcelBizTypeEnum excelBizTypeEnum = method.getAnnotation(ExcelExport.class).value();
        
        // 创建任务实体
        CommonTaskEntity commonTaskEntity = createCommonTaskEntity(excelBizTypeEnum);
        
        // 保存任务到数据库
        commonTaskMapper.insert(commonTaskEntity);
    }
}

技术特色

  • AOP切面编程:实现横切关注点的分离
  • 反射机制:动态获取注解信息和方法参数
  • 任务持久化:将任务信息保存到数据库,确保可靠性

3. 定时任务调度机制

java 复制代码
@Component
public class CommonTaskJob extends BaseJob {
    
    @Override
    public JobResult doRun(String params) {
        // 查询待执行任务
        CommonTaskConditionEntity condition = new CommonTaskConditionEntity();
        condition.setStatusList(Arrays.asList(
            TaskStatusEnum.WAITING.getValue(),
            TaskStatusEnum.RUNNING.getValue()
        ));
        
        List<CommonTaskEntity> tasks = commonTaskMapper.searchByCondition(condition);
        
        // 执行任务
        for (CommonTaskEntity task : tasks) {
            AsyncTaskStrategyContextFactory.getInstance()
                .getStrategy(task.getType())
                .doTask(task);
        }
        
        return JobResult.SUCCESS;
    }
}

核心机制

  • 定时扫描:通过Quartz定时扫描任务队列
  • 策略模式:根据任务类型选择对应的处理器
  • 并发处理:支持多个任务并发执行

4. 异步任务处理器

java 复制代码
@AsyncTask(TaskTypeEnum.EXPORT_EXCEL)
@Service
public class ExcelExportTask implements IAsyncTask {
    
    @Override
    public void doTask(CommonTaskEntity commonTaskEntity) {
        try {
            // 1. 更新任务状态为执行中
            commonTaskEntity.setStatus(TaskStatusEnum.RUNNING.getValue());
            commonTaskMapper.update(commonTaskEntity);
            
            // 2. 获取业务类型和请求参数
            ExcelBizTypeEnum excelBizTypeEnum = getExcelBizTypeEnum(commonTaskEntity.getBizType());
            String requestParam = commonTaskEntity.getRequestParam();
            Object toBean = JSONUtil.toBean(requestParam, aClass);
            
            // 3. 获取对应的Service并执行导出
            String serviceName = this.getServiceName(requestEntity);
            BaseService baseService = (BaseService) SpringBeanUtil.getBean(serviceName);
            String fileName = getFileName(excelBizTypeEnum.getDesc());
            String fileUrl = baseService.export(toBean, fileName, this.getEntityName(requestEntity));
            
            // 4. 更新任务状态为成功
            commonTaskEntity.setFileUrl(fileUrl);
            commonTaskEntity.setStatus(TaskStatusEnum.SUCCESS.getValue());
            
        } catch (Exception e) {
            // 5. 处理失败情况
            handleTaskFailure(commonTaskEntity, e);
        } finally {
            // 6. 更新任务记录并发送通知
            commonTaskMapper.update(commonTaskEntity);
            sendNotifyMessage(commonTaskEntity);
        }
    }
}

处理流程

  • 状态管理:完整的任务状态流转(等待→执行中→成功/失败)
  • 异常处理:完善的异常捕获和失败重试机制
  • 动态调用:通过反射动态获取Service实例
  • 通知机制:任务完成后自动发送通知

最近为了帮助大家找工作,专门建了一些工作内推群,各大城市都有,欢迎各位HR和找工作的小伙伴进群交流,群里目前已经收集了不少的工作内推岗位。加苏三的微信:li_su223,备注:掘金+所在城市,即可进群。

5. 消息通知机制

java 复制代码
@RocketMQMessageListener(
    topic = "${mall.mgt.excelExportTopic:EXCEL_EXPORT_TOPIC}",
    consumerGroup = "${mall.mgt.excelExportGroup:EXCEL_EXPORT_GROUP}"
)
@Component
public class ExcelExportConsumer implements RocketMQListener<MessageExt> {
    
    @Override
    public void onMessage(MessageExt message) {
        String content = new String(message.getBody());
        CommonNotifyEntity commonNotifyEntity = JSONUtil.toBean(content, CommonNotifyEntity.class);
        pushNotify(commonNotifyEntity);
    }
    
    private void pushNotify(CommonNotifyEntity commonNotifyEntity) {
        // 通过WebSocket推送通知
        WebSocketServer.sendMessage(commonNotifyEntity);
        
        // 更新通知状态
        commonNotifyEntity.setIsPush(1);
        commonNotifyMapper.update(commonNotifyEntity);
    }
}

通知特色

  • 异步解耦:通过消息队列实现系统解耦
  • 实时推送:WebSocket确保用户及时收到通知
  • 可靠性保证:消息队列确保通知的可靠传递

技术架构亮点

1. 策略模式 + 工厂模式

java 复制代码
public class AsyncTaskStrategyContextFactory {
    private static Map<Integer, IAsyncTask> asyncTaskMap;
    
    public IAsyncTask getStrategy(Integer taskType) {
        return asyncTaskMap.get(taskType);
    }
}

设计优势

  • 扩展性强 :新增任务类型只需实现IAsyncTask接口
  • 维护性好:每种任务类型独立实现,互不影响
  • 配置灵活:通过工厂模式统一管理任务策略

2. 注解驱动编程

java 复制代码
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface ExcelExport {
    ExcelBizTypeEnum value();
}

编程范式

  • 声明式编程:通过注解声明功能,而非命令式实现
  • 元数据驱动:注解携带的元数据驱动系统行为
  • 代码简洁:业务代码保持简洁,关注点分离

3. 异步任务状态机

状态管理

  • 状态流转:清晰的状态转换逻辑
  • 重试机制:失败任务自动重试,提高成功率
  • 状态持久化:任务状态持久化到数据库

4. 分页大数据处理

java 复制代码
private String doExport(V v, String fileName, String clazzName) {
    RequestConditionEntity conditionEntity = (RequestConditionEntity) v;
    
    // 计算分页参数
    int totalCount = getBaseMapper().searchCount(conditionEntity);
    int sheetCount = totalCount % sheetDataSize == 0 ? 
        totalCount / sheetDataSize : totalCount / sheetDataSize + 1;
    
    // 创建ExcelWriter
    ExcelWriter excelWriter = EasyExcel.write(file).build();
    
    // 分页处理数据
    for (int sheetIndex = 1; sheetIndex <= sheetCount; sheetIndex++) {
        List<K> dataEntities = getBaseMapper().searchByCondition(conditionEntity);
        
        // 写入数据到Sheet
        WriteSheet writeSheet = EasyExcel.writerSheet("Sheet" + sheetIndex)
            .head(Class.forName(clazzName)).build();
        excelWriter.write(dataEntities, writeSheet);
        
        conditionEntity.setPageNo(conditionEntity.getPageNo() + 1);
    }
    
    excelWriter.finish();
    return uploadToOSS(file);
}

处理策略

  • 内存优化:分页查询避免大量数据加载到内存
  • 流式处理:使用EasyExcel的流式API
  • 多Sheet支持:大数据自动分割到多个Sheet
  • 进度可控:分页处理便于监控和中断

技术优势

1. 用户体验优势

  • 即时响应:用户请求后立即返回,无需等待
  • 实时通知:通过WebSocket实时推送导出结果
  • 进度可见:用户可以实时查看导出进度
  • 错误友好:导出失败时提供详细的错误信息

2. 系统性能优势

  • 高并发:异步处理支持高并发导出请求
  • 资源优化:分页处理避免内存溢出
  • 负载均衡:任务队列支持负载均衡
  • 可扩展性:支持水平扩展和垂直扩展

3. 开发维护优势

  • 代码简洁:注解驱动,业务代码简洁
  • 易于扩展:新增业务类型只需添加注解
  • 统一管理:所有导出任务统一管理和监控
  • 错误处理:完善的异常处理和重试机制

4. 运维管理优势

  • 任务监控:完整的任务执行监控
  • 状态管理:清晰的任务状态流转
  • 日志记录:详细的操作日志记录
  • 告警机制:完善的异常告警机制

总结

苏三商城的Excel异步导出机制是一个设计精良、功能完善的企业级解决方案。

它通过以下技术手段实现了高效、稳定、可扩展的异步导出功能:

核心技术栈

  • 注解驱动@ExcelExport注解实现声明式编程
  • AOP切面CommonTaskAspect实现横切关注点分离
  • 策略模式AsyncTaskStrategyContextFactory实现任务策略管理
  • 定时调度:Quartz实现任务定时调度
  • 消息队列:RocketMQ实现异步通知
  • 实时通信:WebSocket实现实时推送
  • 文件存储:OSS实现文件云端存储

设计亮点

  1. 异步解耦:通过任务队列实现请求与处理的解耦
  2. 状态管理:完整的任务状态流转和持久化
  3. 错误处理:完善的异常处理和重试机制
  4. 性能优化:分页处理、流式写入、内存优化
  5. 扩展性强:支持业务类型、导出格式、通知方式的扩展
  6. 监控完善:完整的任务监控和告警机制

业务价值

  • 提升用户体验:异步处理避免长时间等待
  • 提高系统性能:支持大数据量导出和高并发请求
  • 降低开发成本:注解驱动减少重复代码
  • 便于运维管理:统一的任务管理和监控

这套异步导出机制不仅解决了传统同步导出的技术难题,还提供了良好的扩展性和维护性,是苏三商城项目的技术亮点之一,值得在其他项目中推广和应用。

最近准备面试的小伙伴,可以看一下这个宝藏网站(Java突击队):www.susan.net.cn,里面:面试八股文、场景设计题、面试真题、7个项目实战、工作内推什么都有

相关推荐
何中应3 小时前
如何截取PDF内容为图片
java·开发语言·后端·pdf
Jenwein4 小时前
Linux中使用docker的网络问题
后端·docker
华仔啊4 小时前
这20条SQL优化方案,让你的数据库查询速度提升10倍
数据库·后端·mysql
非凡ghost4 小时前
Syncovery Premium(文件同步软件)
前端·javascript·后端
猪猪拆迁队4 小时前
前端图形架构设计:AI生成设计稿落地实践
前端·后端·ai编程
非凡ghost4 小时前
BiliLive-tools(B站录播一站式工具) 中文绿色版
前端·javascript·后端
非凡ghost5 小时前
bkViewer小巧精悍数码照片浏览器 中文绿色版
前端·javascript·后端
间彧5 小时前
Java并发编程:乐观锁、悲观锁、公平锁、非公平锁
后端
间彧5 小时前
Java并发编程锁机制解析:乐观锁、悲观锁、公平锁、非公平锁、可重入锁、独占锁、共享锁
后端