流式分页导出
/**
* 流式导出方法,用于处理大数据量,避免内存溢出
* @param dataFetcher 数据获取函数,接收页码和页面大小,返回分页结果
* @param fileName 文件名
* @param columns 列定义
* @param response HTTP响应
* @param pageSize 每页大小
*/
public static void exportStream(
BiFunction<Integer, Integer, IPage<?>> dataFetcher,
String fileName,
List<Alias> columns,
HttpServletResponse response,
int pageSize) {
SXSSFWorkbook workbook = null;
try {
// 设置响应头
setResponseHeaders(response, fileName);
// 创建SXSSFWorkbook,设置窗口大小为100行(保留在内存中的行数)
workbook = new SXSSFWorkbook(100);
// 创建工作表
Sheet sheet = workbook.createSheet("数据");
// 创建表头
Row headerRow = sheet.createRow(0);
for (int i = 0; i < columns.size(); i++) {
Cell cell = headerRow.createCell(i);
cell.setCellValue(columns.get(i).getLabel());
}
// 分批获取数据并写入
int currentPage = 1;
int rowNum = 1; // 从第二行开始写数据(第一行是表头)
while (true) {
// 获取当前页数据
IPage<?> pageResult = dataFetcher.apply(currentPage, pageSize);
List<?> records = pageResult.getRecords();
// 如果没有数据了,退出循环
if (records == null || records.isEmpty()) {
break;
}
// 将数据写入Excel
for (Object record : records) {
Row row = sheet.createRow(rowNum++);
// 根据字段名获取对应的值并写入单元格
for (int col = 0; col < columns.size(); col++) {
String fieldName = columns.get(col).getProp();
Object value = getFieldValue(record, fieldName);
Cell cell = row.createCell(col);
if (value != null) {
cell.setCellValue(value.toString());
} else {
cell.setCellValue("");
}
}
}
// 如果当前页数据少于页面大小,说明已经是最后一页
if (records.size() < pageSize) {
break;
}
currentPage++;
}
// 写入输出流
workbook.write(response.getOutputStream());
} catch (Exception e) {
log.error("流式导出Excel失败", e);
throw new RuntimeException("导出Excel失败", e);
} finally {
if (workbook != null) {
try {
workbook.close();
// 清理临时文件
workbook.dispose();
} catch (Exception e) {
log.warn("关闭Excel工作簿时发生异常", e);
}
}
}
}
/**
* 通过反射获取对象字段值
*/
private static Object getFieldValue(Object obj, String fieldName) {
try {
java.lang.reflect.Field field = obj.getClass().getDeclaredField(fieldName);
field.setAccessible(true);
return field.get(obj);
} catch (Exception e) {
log.warn("获取字段值失败: " + fieldName, e);
return null;
}
}Spring Batch框架介绍
Spring Batch 是一个轻量级、功能完善的批处理框架,专为在企业级 Java 应用中高效处理大量数据而设计。它基于 Spring 框架构建,支持简单到复杂的批处理场景,并提供事务管理、任务重启、跳过失败记录、监控等关键能力。
核心特性
轻量且易集成:作为 Spring 生态的一部分,可无缝集成到 Spring Boot 项目中。
支持大数据量处理:通过分块(Chunk-oriented)处理机制,减少内存占用,提升性能。
健壮性保障:
事务管理(每个 chunk 提交一次事务)
断点续跑(作业失败后可从上次中断处重启)
跳过(Skip)与重试(Retry)机制
可扩展性强:支持自定义
ItemReader、ItemProcessor、ItemWriter,以及分布式分区处理。监控与日志:通过
JobRepository持久化作业元数据,便于跟踪执行状态。
核心组件
Job:代表一个完整的批处理任务,由一个或多个 Step 组成。
Step:Job 的执行单元,通常包含:
ItemReader:从数据源(如文件、数据库)读取数据。
ItemProcessor:对数据进行业务逻辑处理(可选)。
ItemWriter:将处理后的数据写入目标位置。
JobLauncher:用于启动 Job。
JobRepository:存储 Job 执行的元数据(如状态、参数、结果),支持内存或数据库(推荐生产环境使用数据库)。
典型使用场景
日终对账(金融系统)
数据迁移与同步
报表生成
日志清洗与分析
批量导入/导出(如 CSV → 数据库)
CLKLOG框架介绍
clklog官网
ClkLog是一款支持快速私有化部署的开源埋点分析系统。兼容Web、App、小程序等多端埋点数据采集,帮助你快速洞察用户访问路径、行为轨迹,并生成多维用户画像。
ClkLog:一站式用户行为分析解决方案
ClkLog,一款支持快速私有化部署的开源埋点分析系统,它能够帮助你迅速洞察用户访问路径、行为轨迹,并构建多维用户画像。这款强大的工具兼容Web、App、小程序等多个终端的数据采集,为你的业务增长提供强力支持。
ClkLog:功能强大的用户行为分析系统
ClkLog是一个开源的用户行为分析平台,其核心在于记录和分析用户的在线行为数据,从而构建出详尽的用户画像。它提供了多样化的数据采集方式,包括代码埋点、可视化埋点以及无埋点,并能全面支持网页、App、小程序等多种终端的数据采集。ClkLog采用前后端分离架构,基于神策分析SDK以及ClickHouse数据库,不仅支持私有化部署,而且部署过程十分便捷。它提供了丰富的数据分析功能,如访问统计、用户画像、漏斗分析以及自定义SQL查询等,拿电商、教育以及社交等场景来说,都能从中受益。
ClkLog:开源且灵活的部署方案
ClkLog是一个开源且可商用的系统,遵循AGPL 3.0协议。其技术栈涵盖Java、Vue、Element UI以及ECharts等,具备高并发处理能力以及强大的实时性。它还提供了直观的可视化界面,以及丰富的数据展示功能,能够帮助用户进行精细化运营,从而助力业务增长。ClkLog提供了多种部署方案,包括私有化部署以及开源版本,方便用户快速搭建并且进行扩展,非常适合中小团队以及企业使用。
ClkLog:便捷的资源获取渠道
ClkLog提供了丰富的文档以及社区支持,包括GitHub项目、在线演示以及技术支持等。你可以通过其官网(https://clklog.com/)以及GitHub项目地址(https://github.com/clklog)获取更多信息。
clklog官方网站入口网址:
clklog官网:https://clklog.com/
OpenI小编发现clklog网站非常受用户欢迎,请访问clklog官网网址入口试用。
瞬间即永恒