Jeffrey's Home

路漫漫其修远兮,吾将上下而求索

瞬间

流式分页导出

/**
     * 流式导出方法,用于处理大数据量,避免内存溢出
     * @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;
        }
    }

06-02 08:39
GitHub Contributions

GitHub 热力图加载失败

文档中心

Documentation

View All

暂无文档项目,准备大作中

Administrator

流式分页导出

/**
     * 流式导出方法,用于处理大数据量,避免内存溢出
     * @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;
        }
    }

Administrator

Spring Batch框架介绍

Spring Batch‌ 是一个轻量级、功能完善的批处理框架,专为在企业级 Java 应用中高效处理大量数据而设计。它基于 Spring 框架构建,支持简单到复杂的批处理场景,并提供事务管理、任务重启、跳过失败记录、监控等关键能力。

核心特性

  • 轻量且易集成‌:作为 Spring 生态的一部分,可无缝集成到 Spring Boot 项目中。

  • 支持大数据量处理‌:通过分块(Chunk-oriented)处理机制,减少内存占用,提升性能。

  • 健壮性保障‌:

    • 事务管理(每个 chunk 提交一次事务)

    • 断点续跑(作业失败后可从上次中断处重启)

    • 跳过(Skip)与重试(Retry)机制

  • 可扩展性强‌:支持自定义 ItemReaderItemProcessorItemWriter,以及分布式分区处理。

  • 监控与日志‌:通过 JobRepository 持久化作业元数据,便于跟踪执行状态。

核心组件

  • Job‌:代表一个完整的批处理任务,由一个或多个 Step 组成。

  • Step‌:Job 的执行单元,通常包含:

    • ItemReader‌:从数据源(如文件、数据库)读取数据。

    • ItemProcessor‌:对数据进行业务逻辑处理(可选)。

    • ItemWriter‌:将处理后的数据写入目标位置。

  • JobLauncher‌:用于启动 Job。

  • JobRepository‌:存储 Job 执行的元数据(如状态、参数、结果),支持内存或数据库(推荐生产环境使用数据库)。

典型使用场景

  • 日终对账(金融系统)

  • 数据迁移与同步

  • 报表生成

  • 日志清洗与分析

  • 批量导入/导出(如 CSV → 数据库)

Administrator

CLKLOG框架介绍

clklog官网

ClkLog是一款支持快速私有化部署的开源埋点分析系统。兼容Web、App、小程序等多端埋点数据采集,帮助你快速洞察用户访问路径、行为轨迹,并生成多维用户画像。

clklog

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官网网址入口试用。

图库

Focus Moments

View All

暂无图库分组