前言
在大型电商系统中,数据导出是一个高频且重要的功能需求。
传统的同步导出方式在面对大数据量时往往会导致请求超时、内存溢出等问题,严重影响用户体验。
苏三商城项目创新性地设计并实现了一套完整的Excel异步导出机制,通过注解驱动、任务队列、定时调度、消息通知等技术手段,完美解决了大数据量导出的技术难题,成为项目的重要技术亮点。
最近准备面试的小伙伴,可以看一下这个宝藏网站(Java突击队):www.susan.net.cn,里面:面试八股文、场景设计题、面试真题、7个项目实战、工作内推什么都有。
系统架构设计
整体架构图

核心组件说明
- 注解驱动层 :通过
@ExcelExport注解实现声明式编程 - 切面处理层 :
CommonTaskAspect负责拦截和任务创建 - 任务管理层 :
ExcelExportTask执行具体的导出逻辑 - 调度引擎层:基于Quartz的定时任务调度
- 消息通知层:RocketMQ + WebSocket实现异步通知
- 存储层: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实现文件云端存储
设计亮点
- 异步解耦:通过任务队列实现请求与处理的解耦
- 状态管理:完整的任务状态流转和持久化
- 错误处理:完善的异常处理和重试机制
- 性能优化:分页处理、流式写入、内存优化
- 扩展性强:支持业务类型、导出格式、通知方式的扩展
- 监控完善:完整的任务监控和告警机制
业务价值
- 提升用户体验:异步处理避免长时间等待
- 提高系统性能:支持大数据量导出和高并发请求
- 降低开发成本:注解驱动减少重复代码
- 便于运维管理:统一的任务管理和监控
这套异步导出机制不仅解决了传统同步导出的技术难题,还提供了良好的扩展性和维护性,是苏三商城项目的技术亮点之一,值得在其他项目中推广和应用。
最近准备面试的小伙伴,可以看一下这个宝藏网站(Java突击队):www.susan.net.cn,里面:面试八股文、场景设计题、面试真题、7个项目实战、工作内推什么都有。