当前位置: 首页 > article >正文

别再让脏数据入库了!用EasyExcel+自定义监听器,搞定Excel导入的6种常见校验(附完整代码)

Excel数据导入防御性编程实战基于EasyExcel的6层校验体系设计每次业务系统上线新功能最让我头疼的不是复杂逻辑实现而是那些看似简单的Excel导入。上周又遇到生产事故市场部门上传的客户数据因格式混乱导致系统主表污染整个周末都在紧急回滚。痛定思痛我决定系统梳理Excel导入的防御体系分享这套基于EasyExcel的六重数据校验架构。1. 校验体系设计原则在电商系统中一次完整的Excel导入需要经历从文件上传到持久化的完整链路。优秀的校验设计应该像洋葱一样层层包裹前置校验层文件基础属性验证格式、大小等结构校验层模板合规性检查表头匹配等业务校验层字段级规则验证必填、格式等逻辑校验层跨行数据一致性去重、关联等持久化校验层数据库约束预检查唯一键等异常处理层友好错误反馈机制// 校验流程伪代码 public void importExcel(MultipartFile file) { validateFile(file); // 前置校验 validateTemplate(file); // 结构校验 ListData data parseData(file); validateFields(data); // 业务校验 validateBusiness(data); // 逻辑校验 validateDatabase(data); // 持久化校验 saveData(data); // 最终入库 }2. 文件级防御校验2.1 格式校验实现最基础的防御线需要拦截非法文件类型。推荐使用文件魔数校验而非扩展名判断防止伪造文件private static final String XLS_SIGNATURE D0CF11E0; private static final String XLSX_SIGNATURE 504B0304; public void validateFileType(InputStream is) throws IOException { byte[] header new byte[4]; is.read(header); String hexSignature bytesToHex(header); if (!hexSignature.startsWith(XLS_SIGNATURE) !hexSignature.startsWith(XLSX_SIGNATURE)) { throw new ValidationException(非法的Excel文件格式); } is.reset(); // 重置流供后续读取 }2.2 空文件检测空文件需要特殊处理常规方案有两种检测方式优点缺点文件大小检测性能高O(1)无法识别只有表头的文件内容行数检测准确度高需要解析文件O(n)POI预读检测兼容各种复杂情况内存消耗较大推荐组合方案public void validateEmpty(MultipartFile file) { // 第一重快速大小检查 if (file.isEmpty()) { throw new ValidationException(文件内容为空); } // 第二重精确行数检查 try (ExcelReader reader EasyExcel.read(file.getInputStream()).build()) { ReadSheet sheet EasyExcel.readSheet(0).headRowNumber(0).build(); if (reader.read(sheet).isEmpty()) { throw new ValidationException(数据行数为空); } } }3. 模板校验体系3.1 动态表头匹配传统硬编码表头校验缺乏灵活性。我们可以通过注解驱动实现动态校验Data public class ProductImportDTO { ExcelCheck(required true, regex ^\\d{8}$) ExcelProperty(商品编码*) private String productCode; ExcelCheck(minLength 2, maxLength 50) ExcelProperty(商品名称*) private String productName; } // 在监听器中自动校验 Override public void invokeHeadMap(MapInteger, String headMap, AnalysisContext context) { MapString, Field fieldMap getCheckFieldMap(); // 反射获取校验字段 fieldMap.forEach((name, field) - { if (!headMap.containsValue(name)) { errors.add(缺失必要列: name); } }); }3.2 多sheet校验复杂业务常需要多sheet导入可通过Sheet校验策略实现public class MultiSheetListener extends AnalysisEventListenerObject { private final MapInteger, SheetStrategy strategies; Override public void invoke(Object data, AnalysisContext context) { int sheetNo context.readSheetHolder().getSheetNo(); strategies.get(sheetNo).validate(data); } } // 注册不同sheet的校验策略 MapInteger, SheetStrategy strategies Map.of( 0, new ProductStrategy(), 1, new InventoryStrategy() );4. 数据行级校验4.1 字段基础校验通过组合校验器处理常见规则public class FieldValidator { private static final ListChecker checkers Arrays.asList( new RequiredChecker(), new LengthChecker(), new RegexChecker(), new EnumChecker() ); public static void validate(Object obj) { for (Checker checker : checkers) { checker.check(obj); } } } // 在监听器中调用 Override public void invoke(T data, AnalysisContext context) { FieldValidator.validate(data); validData.add(data); }4.2 跨行业务校验典型场景如批次去重推荐使用上下文感知校验器public class DuplicateChecker { private final SetString uniqueKeys new HashSet(); public void check(Product product) { String key product.getCategory() : product.getCode(); if (uniqueKeys.contains(key)) { throw new ValidationException(重复商品记录: key); } uniqueKeys.add(key); } }5. 异常处理机制5.1 错误信息收集设计错误上下文对象贯穿整个校验流程public class ErrorContext { private final ListCellError cellErrors new ArrayList(); private final ListRowError rowErrors new ArrayList(); public void addCellError(int row, int col, String message) { cellErrors.add(new CellError(row, col, message)); } public void addRowError(int row, String message) { rowErrors.add(new RowError(row, message)); } } // 在控制器层统一处理 ExceptionHandler(ValidationException.class) public ResponseEntityErrorResult handleError(ValidationException e) { return ResponseEntity.badRequest() .body(new ErrorResult(e.getErrors())); }5.2 错误报告生成提供多种错误反馈方式即时响应在API返回中包含错误明细错误文件生成标注错误的Excel文件错误看板在管理后台展示错误统计public void generateErrorReport(ErrorContext context) { ExcelWriter writer EasyExcel.write(错误报告.xlsx) .registerWriteHandler(new ErrorCellStyleHandler()) .build(); writer.write(context.getValidData(), EasyExcel.writerSheet(正确数据).build()); writer.write(context.getErrors(), EasyExcel.writerSheet(错误明细).build()); writer.finish(); }6. 性能优化实践6.1 校验执行策略根据数据量选择不同策略策略类型适用场景内存消耗响应速度全量校验小数据量(1万行)高快分批校验中等数据量中中流式校验大数据量(10万行)低慢// 流式校验示例 public class StreamingValidator { public void validate(InputStream is, ConsumerValidResult callback) { EasyExcel.read(is, new AnalysisEventListener() { Override public void invoke(Object data, AnalysisContext context) { // 逐行校验 ValidationResult result validateRow(data); callback.accept(convert(result)); } }).sheet().doRead(); } }6.2 缓存优化对字典类校验如地区编码使用校验缓存public class AreaCodeValidator { private final LoadingCacheString, Boolean cache Caffeine.newBuilder() .maximumSize(10_000) .build(this::validateFromDB); public boolean isValid(String code) { return cache.get(code); } }这套校验体系在我们订单导入场景中将数据错误率从最初的15%降到了0.3%以下。最关键的收获是前置校验的成本永远比事后修复低。特别是在处理金融数据时某个字段的格式错误可能导致后续批量作业全部失败。现在团队已经形成规范所有导入功能必须通过校验测试用例才能上线。

相关文章:

别再让脏数据入库了!用EasyExcel+自定义监听器,搞定Excel导入的6种常见校验(附完整代码)

Excel数据导入防御性编程实战:基于EasyExcel的6层校验体系设计 每次业务系统上线新功能,最让我头疼的不是复杂逻辑实现,而是那些看似简单的Excel导入。上周又遇到生产事故:市场部门上传的客户数据因格式混乱导致系统主表污染&…...

如何永久保存微信聊天记录:WeChatMsg完整数据备份与可视化指南

如何永久保存微信聊天记录:WeChatMsg完整数据备份与可视化指南 【免费下载链接】WeChatMsg 提取微信聊天记录,将其导出成HTML、Word、CSV文档永久保存,对聊天记录进行分析生成年度聊天报告 项目地址: https://gitcode.com/GitHub_Trending/…...

Zotero PDF Translate:一站式跨语言文献阅读的高效解决方案

Zotero PDF Translate:一站式跨语言文献阅读的高效解决方案 【免费下载链接】zotero-pdf-translate Translate PDF, EPub, webpage, metadata, annotations, notes to the target language. Support 20 translate services. 项目地址: https://gitcode.com/gh_mir…...

零基础部署Qwen3-ASR-0.6B:支持52种语言的语音识别模型快速上手

零基础部署Qwen3-ASR-0.6B:支持52种语言的语音识别模型快速上手 1. 为什么选择Qwen3-ASR-0.6B 语音识别技术正在改变我们与设备交互的方式。Qwen3-ASR-0.6B作为一款轻量级但功能强大的语音识别模型,特别适合想要快速搭建多语言语音识别系统的开发者。它…...

Electron进程通信实战:从单向通知到双向文件选择(Vue3 + Vite项目示例)

Electron进程通信实战:从单向通知到双向文件选择(Vue3 Vite项目示例) 引言 在现代桌面应用开发中,Electron凭借其跨平台特性和Web技术栈的亲和力,已成为许多开发者的首选框架。然而,真正掌握Electron的核心…...

企业任务管理软件哪个好用?10款主流工具测评盘点

本文将深入对比10款工作任务管理系统:Worktile、PingCode、Jira Confluence、monday.com、Asana、ClickUp、Wrike、Smartsheet、Teamwork、Trello。很多企业在选工作任务管理系统时,最头疼的其实不是“工具太少”,而是“工具太多&#xff0c…...

基于 Redis 实现社交 Feed 流:收件箱模式 + 时间线滚动查询

本文基于Redis ZSet实现社交平台关注 Feed 流功能,采用收件箱模式(推模式) 完成博客发布时的粉丝消息推送,结合时间戳 偏移量实现无感知滚动分页查询,解决传统分页卡顿、数据重复 / 丢失问题。附带完整业务代码、核心…...

网盘直链解析工具:基于JavaScript的八大网盘下载地址获取方案

网盘直链解析工具:基于JavaScript的八大网盘下载地址获取方案 【免费下载链接】Online-disk-direct-link-download-assistant 一个基于 JavaScript 的网盘文件下载地址获取工具。基于【网盘直链下载助手】修改 ,支持 百度网盘 / 阿里云盘 / 中国移动云盘…...

BitNet-b1.58-2B-4T-GGUF 在计算机组成原理教学中的辅助应用

BitNet-b1.58-2B-4T-GGUF 在计算机组成原理教学中的辅助应用 1. 教学痛点与解决方案 计算机组成原理作为计算机专业的核心基础课程,长期面临概念抽象、实践门槛高的教学挑战。传统教学方式中,学生往往难以直观理解CPU流水线、缓存一致性等复杂机制&…...

YimMenu终极实战指南:免费GTA5辅助工具完整配置与高效使用手册

YimMenu终极实战指南:免费GTA5辅助工具完整配置与高效使用手册 【免费下载链接】YimMenu YimMenu, a GTA V menu protecting against a wide ranges of the public crashes and improving the overall experience. 项目地址: https://gitcode.com/GitHub_Trending…...

DLSS Swapper终极指南:5分钟学会智能管理游戏DLSS文件,彻底告别手动替换烦恼

DLSS Swapper终极指南:5分钟学会智能管理游戏DLSS文件,彻底告别手动替换烦恼 【免费下载链接】dlss-swapper 项目地址: https://gitcode.com/GitHub_Trending/dl/dlss-swapper 你是否曾经为了提升游戏帧率,手动在各个游戏目录中寻找并…...

nli-MiniLM2-L6-H768模型解析:深入理解其轻量级设计背后的计算机组成原理考量

nli-MiniLM2-L6-H768模型解析:深入理解其轻量级设计背后的计算机组成原理考量 1. 引言:为什么需要轻量级模型 在AI模型部署的实践中,我们常常面临一个核心矛盾:模型性能与计算资源消耗之间的权衡。nli-MiniLM2-L6-H768这类轻量级…...

Miniconda-Python3.11镜像:快速搭建Web开发/数据分析环境

Miniconda-Python3.11镜像:快速搭建Web开发/数据分析环境 1. 为什么选择Miniconda-Python3.11 Python作为当下最流行的编程语言之一,在Web开发、数据分析、人工智能等领域都有广泛应用。但Python环境管理一直是个令人头疼的问题——不同项目可能需要不…...

有限差分法模拟地震波场时,如何避免数值不稳定和频散?PML边界设置实战经验分享

有限差分法模拟地震波场的稳定性优化与PML边界实战指南 地震波场数值模拟是地球物理勘探和地震学研究的重要工具,而有限差分法因其实现简单、计算高效成为最常用的数值模拟方法之一。但在实际应用中,数值不稳定和频散问题常常困扰着研究者,尤…...

SNP亮相2026 SAP大消费行业峰会,以数据为核心驱动企业转型升级

2026年4月24日,SAP大消费行业峰会在上海圆满落幕。本次峰会汇聚了大消费、零售、生命科学领域的百余位企业领袖与专家。SNP作为一家致力于数据迁移的专业软件及服务提供商与德勤、海通安恒等核心生态伙伴受邀出席,共同探讨AI时代下的企业增长新路径。AI重…...

别再只懂RBAC了!用ABAC搞定复杂业务权限,看这篇就够了(附Spring Security实战)

从RBAC到ABAC:构建下一代动态权限系统的实战指南 在电商后台系统开发中,你是否遇到过这样的场景:VIP用户只能在促销时段修改特定类目商品价格,而普通管理员仅能在工作日操作非敏感商品?传统RBAC(基于角色的…...

【转行大模型】大龄程序员转行AI大模型:高薪、前沿与实战全攻略

前言 对于大龄程序员而言,转行到AI大模型领域是一个既充满挑战又极具吸引力的选择。在这个领域,您将有机会接触到最新的技术趋势,参与到前沿的项目中,并且有可能获得更高的薪酬。下面是一些具体的步骤和建议,帮助您顺…...

抖音批量下载终极解决方案:从零开始实战,告别繁琐操作

抖音批量下载终极解决方案:从零开始实战,告别繁琐操作 【免费下载链接】douyin-downloader A practical Douyin downloader for both single-item and profile batch downloads, with progress display, retries, SQLite deduplication, and browser fal…...

# 用 Python 构建碳足迹追踪工具:从代码到可视化,实现绿色编程新实践在当前全球关注碳中和的大背景下,**开发者不仅是技术的创

用 Python 构建碳足迹追踪工具:从代码到可视化,实现绿色编程新实践 在当前全球关注碳中和的大背景下,开发者不仅是技术的创造者,更应成为环境可持续性的践行者。本文将带你用 Python 编写一个轻量级但功能完整的 碳足迹计算与分析…...

新手必看:用Mission Planner和QGroundControl调参,手机和电脑哪个更方便?

Mission Planner与QGroundControl实战对比:无人机调参工具选型指南 刚组装完第一台DIY无人机的兴奋感还没消退,我就被一个现实问题难住了——该用电脑上的Mission Planner还是手机端的QGroundControl进行飞控调参?这个问题看似简单&#xff0…...

2 51单片机引脚

一、单片机名称的含义这里以STC 89C52RC40I-PDIP402538HBSB06.X90C为例STC表示厂商——STC公司(宏晶科技)89——8051内核,兼容标准MCS-51指令集C——工作电压,C: 5.5~3.3V 、 LE: 3.6~2.0V52表示型号序号——程序空间ROM大小——5…...

别再只看单个差异基因了!用R语言clusterProfiler包做ORA富集分析,给你的RNA-seq结果找个靠谱的‘解释’

从基因列表到生物学故事:用R语言解锁RNA-seq数据的通路级解读 第一次拿到RNA-seq差异分析结果时,看着Excel里那几百个"显著差异基因",我盯着屏幕发呆了半小时——这些基因到底说明了什么生物学问题?如果你也经历过这种&…...

算法打卡第二十天 / 150.逆波兰表达式求值

一、今日学习任务第20天 栈的经典应用 核心要求:实现逆波兰表达式的求值操作,掌握栈这一核心解法,理解栈在表达式计算中的底层逻辑。 前置建议:回顾栈的基础数据结构与进出栈操作,理解逆波兰表达式(后缀表达…...

像说话一样写程序:图解 Python 常用基础语法

把代码当成日常对话 很多人一看到编程代码,脑海里浮现的往往是复杂的数学公式或者晦涩的机器指令,瞬间就产生了畏难情绪。其实,Python 之所以被称为“可执行的伪代码”,就是因为它的设计初衷是让程序员像说话一样去表达逻辑。我们…...

从零开始写代码:Python 基础语法快速上手攻略

变量与数据类型:给数据贴上标签 编程的第一步,就是学会如何“存储”和“识别”数据。在 Python 中,你不需要像其他语言那样声明复杂的类型,只需给数据起个名字(变量),Python 会自动识别它是数字…...

旋转机械故障诊断特征表达与智能识别【附代码】

✅ 博主简介:擅长数据搜集与处理、建模仿真、程序设计、仿真代码、论文写作与指导,毕业论文、期刊论文经验交流。 ✅ 如需沟通交流,扫描文章底部二维码。(1)优化变分互无量纲特征与变分模态分解的联合特征提取&#xf…...

终极指南:5分钟掌握KMS智能激活工具,永久告别Windows和Office激活烦恼

终极指南:5分钟掌握KMS智能激活工具,永久告别Windows和Office激活烦恼 【免费下载链接】KMS_VL_ALL_AIO Smart Activation Script 项目地址: https://gitcode.com/gh_mirrors/km/KMS_VL_ALL_AIO 你是否曾因Windows系统频繁弹出激活提醒而分心工作…...

PyWxDump技术剖析:数据解密工具的合规边界与安全启示

PyWxDump技术剖析:数据解密工具的合规边界与安全启示 【免费下载链接】PyWxDump 删库 项目地址: https://gitcode.com/GitHub_Trending/py/PyWxDump 技术挑战与应对策略的双重博弈 在数字隐私与数据安全日益重要的今天,微信数据解密工具PyWxDump…...

告别扫描PDF无法搜索的困扰:OCRmyPDF让你的文档“开口说话“

告别扫描PDF无法搜索的困扰:OCRmyPDF让你的文档"开口说话" 【免费下载链接】OCRmyPDF OCRmyPDF adds an OCR text layer to scanned PDF files, allowing them to be searched 项目地址: https://gitcode.com/GitHub_Trending/oc/OCRmyPDF 你是否曾…...

三步告别魔兽争霸3闪退:WarcraftHelper现代兼容性修复指南

三步告别魔兽争霸3闪退:WarcraftHelper现代兼容性修复指南 【免费下载链接】WarcraftHelper Warcraft III Helper , support 1.20e, 1.24e, 1.26a, 1.27a, 1.27b 项目地址: https://gitcode.com/gh_mirrors/wa/WarcraftHelper 你是否曾满怀期待地打开魔兽争霸…...