java

关注公众号 jb51net

关闭
首页 > 软件编程 > java > java Excel异步导出

java实现Excel高性能异步导出的完整方案详解

作者:苏三说技术

在大型电商系统中,数据导出是一个高频且重要的功能需求,本文将设计实现一套完整的Excel异步导出机制,通过注解驱动、任务队列、定时调度、消息通知等技术手段,完美解决了大数据量导出的技术难题,成为项目的重要技术亮点

前言

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

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

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

系统架构设计

整体架构图

核心组件说明

异步导出流程详解

完整流程图

关键步骤分析

1. 注解驱动任务创建

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

设计亮点

2. 切面拦截与任务创建

@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);
    }
}

技术特色

3. 定时任务调度机制

@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;
    }
}

核心机制

4. 异步任务处理器

@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);
        }
    }
}

处理流程

5. 消息通知机制

@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);
    }
}

通知特色

技术架构亮点

1. 策略模式 + 工厂模式

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

设计优势

2. 注解驱动编程

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface ExcelExport {
    ExcelBizTypeEnum value();
}

编程范式

3. 异步任务状态机

状态管理

4. 分页大数据处理

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);
}

处理策略

技术优势

1. 用户体验优势

2. 系统性能优势

3. 开发维护优势

4. 运维管理优势

总结

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

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

核心技术栈

设计亮点

业务价值

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

到此这篇关于java实现Excel高性能异步导出的完整方案详解的文章就介绍到这了,更多相关java Excel异步导出内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

您可能感兴趣的文章:
阅读全文