EasyExcel 数据字典转换器实战:注解驱动设计

一、场景痛点与解决方案

1. 问题背景

在 Excel 导入导出场景中,开发者常面临以下问题:

  • 数据可读性差:数据库存储的字典值(如 1、true)直接导出时难以理解
  • 双向转换复杂:导入时需将用户输入的标签反向解析为存储值
  • 代码侵入性强:硬编码字典类型导致业务逻辑与字典管理耦合

2. 设计方案

在这里插入图片描述

二、核心实现解析

1. 注解驱动设计

在这里插入图片描述
代码示例

@Data
public class ConfigRespVO {// 导出列声明 + 字典类型绑定@ExcelProperty(value = "参数类型", converter = DictConvert.class)@DictFormat(DictTypeConstants.CONFIG_TYPE) private Integer type;
}

2. 双向转换流程

导出流程(值 → 标签)

Excel DictConvert DictService 请求转换值(1) getLabel("config_type", 1) "文本类型" 写入单元格 Excel DictConvert DictService

导入流程(标签 → 值)

Excel DictConvert DictService Java 读取单元格("文本类型") parseValue("config_type", "文本类型") "1" 设置Integer类型字段值 Excel DictConvert DictService Java

三、关键技术实现

1. 转换器核心类

@Slf4j
public class DictConvert implements Converter<Object> {@Overridepublic Class<?> supportJavaTypeKey() {throw new UnsupportedOperationException("暂不支持,也不需要");}@Overridepublic CellDataTypeEnum supportExcelTypeKey() {throw new UnsupportedOperationException("暂不支持,也不需要");}@Overridepublic Object convertToJavaData(ReadCellData readCellData, ExcelContentProperty contentProperty,GlobalConfiguration globalConfiguration) {// 使用字典解析String type = getType(contentProperty);String label = readCellData.getStringValue();//通过type(sex)和label(女)获取value(0)String value = DictFrameworkUtils.parseDictDataValue(type, label);if (value == null) {log.error("[convertToJavaData][type({}) 解析不掉 label({})]", type, label);return null;}// 将 String 的 value 转换成对应的属性Class<?> fieldClazz = contentProperty.getField().getType();return Convert.convert(fieldClazz, value);}@Overridepublic WriteCellData<String> convertToExcelData(Object object, ExcelContentProperty contentProperty,GlobalConfiguration globalConfiguration) {// 空时,返回空if (object == null) {return new WriteCellData<>("");}// 使用字典格式化String type = getType(contentProperty);String value = String.valueOf(object);//通过type(sex)和value(0)获取label(女)String label = DictFrameworkUtils.getDictDataLabel(type, value);if (label == null) {log.error("[convertToExcelData][type({}) 转换不了 label({})]", type, value);return new WriteCellData<>("");}// 生成 Excel 小表格return new WriteCellData<>(label);}/*** 通过注解获取**/private static String getType(ExcelContentProperty contentProperty) {return contentProperty.getField().getAnnotation(DictFormat.class).value();}}

2. 注解定义

/*** 字典格式化* <p>* 实现将字典数据的值,格式化成字典数据的标签*/
@Target({ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
@Inherited
public @interface DictFormat {/*** 例如说,SysDictTypeConstants、InfDictTypeConstants** @return 字典类型*/String value();
}

四、设计亮点总结

设计维度实现方案解决的问题
声明式配置通过组合注解实现配置解耦业务代码与字典逻辑
类型安全转换使用Hutool的Convert工具自动处理String→Integer等类型转换
统一异常处理捕获异常并记录错误日志避免Excel解析中断
可扩展性支持任意字典类型配置方便新增字典类型

五、最佳实践建议

1. 常量统一管理

建议创建字典类型常量类:

public class DictTypeConstants {public static final String CONFIG_TYPE = "infra_config_type";public static final String BOOLEAN_STRING = "sys_boolean_string";
}

2. 单元测试方案

public class DictConvertTest {@Testvoid testExport() {ConfigRespVO vo = new ConfigRespVO();vo.setType(1);// 导出验证Excel内容包含"文本类型"EasyExcel.write("test.xlsx", ConfigRespVO.class).sheet().doWrite(Collections.singletonList(vo));}@Testvoid testImport() {// 准备包含"文本类型"的Excel文件List<ConfigRespVO> list = EasyExcel.read("test.xlsx").head(ConfigRespVO.class).sheet().doReadSync();assertEquals(1, list.get(0).getType()); // 验证转换结果}
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/bicheng/75561.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

五种音频器件综合对比——《器件手册--音频器件》

目录 音频器件 简述 1. 扬声器&#xff08;Speakers&#xff09; 2. 麦克风&#xff08;Microphones&#xff09; 3. 放大器&#xff08;Amplifiers&#xff09; 4. 音频接口&#xff08;Audio Interfaces&#xff09; 5. 音频处理器&#xff08;Audio Processors&#xff09…

红宝书第二十九讲:详解编辑器和IDE:VS Code与WebStorm

红宝书第二十九讲&#xff1a;详解编辑器和IDE&#xff1a;VS Code与WebStorm 资料取自《JavaScript高级程序设计&#xff08;第5版&#xff09;》。 查看总目录&#xff1a;红宝书学习大纲 一、核心区别&#xff1a;编辑器与IDE 代码编辑器&#xff08;如VS Code&#xff09…

虚拟电商-话费充值业务(五)充值成功逻辑和网络异常重试逻辑

一、网络异常重试逻辑编写 如果在对接供应商的过程中出现了网络异常&#xff0c;我们需要做一个补偿机制&#xff0c;在任务类型枚举类&#xff1a;TaskTypeEnum中有一种业务状态码是针对远程调用失败的 步骤一&#xff1a;在对接供应商的方法&#xff1a;SupplierServiceImp…

从零构建大语言模型全栈开发指南:第四部分:工程实践与部署-4.3.3低代码开发:快速构建行业应用(电商推荐与金融风控案例)

👉 点击关注不迷路 👉 点击关注不迷路 👉 点击关注不迷路 文章大纲 从零构建大语言模型全栈开发指南-第四部分:工程实践与部署4.3.3 低代码开发:快速构建行业应用(电商推荐与金融风控案例)1. 低代码与AI结合的核心价值2. 电商推荐系统案例2.1 技术架构与实现2.2 性能…

Table as Thought论文精读

标题&#xff1a;Table as Thought: Exploring Structured Thoughts in LLM Reasoning 作者&#xff1a;Zhenjie Sun, Naihao Deng, Haofei Yu, Jiaxuan You 单位&#xff1a;University of Illinois Urbana-Champaign, University of Michigan 摘要&#xff1a; llm的推理…

ubuntu18 server版花屏问题

新搞了一台dellT150的塔式服务器&#xff0c;装的ubuntu18 server版。 开机后遇到花屏&#xff0c;或者卡在开机界面的问题&#xff0c;和售后技术沟通这个情况是ubuntu自带的显卡驱动包兼容问题。需要做如下设置&#xff1a; 解决&#xff1a; 1.开机&#xff0c;连续按下e…

【MySQL】理解MySQL的双重缓冲机制:Buffer Pool与Redo Log的协同之道

在数据库系统中&#xff0c;内存与磁盘的读写性能差距始终是需要解决的核心问题。当注意到Redo Log和Buffer Pool都采用"先写内存再刷盘"的设计时&#xff0c;一个自然的问题浮现&#xff1a;既然两者都需要维护内存数据并定期持久化&#xff0c;为何需要双重缓冲机制…

PMP考试改革解读:新题型+5A通关秘籍

2024年&#xff0c;项目管理协会&#xff08;PMI&#xff09;对PMP考试进行了重大调整&#xff0c;从考试形式、题型分布到知识领域均进行了优化升级。本文结合PMI官方公告与一线教研经验&#xff0c;深度解析改革要点&#xff0c;并提供针对性通关策略&#xff0c;助你高效冲刺…

【Django】教程-10-ajax请求Demo,结合使用

【Django】教程-1-安装创建项目目录结构介绍 【Django】教程-2-前端-目录结构介绍 【Django】教程-3-数据库相关介绍 【Django】教程-4-一个增删改查的Demo 【Django】教程-5-ModelForm增删改查规则校验【正则钩子函数】 【Django】教程-6-搜索框-条件查询前后端 【Django】教程…

RabbitMQ高级特性1

RabbitMQ高级特性1 一.消息确认1.消息确认机制2.手动确认代码肯定确认否定确认1否定确认2Spring中的代码 二.持久性1.交换机持久化2.队列的持久化3.消息的持久化非持久化代码实现三方面都持久化&#xff0c;数据也会丢失 三.发送方确认1.Confirm确认模式2.return返回模式 四.总…

Java网络编程NIO

一、NIO是什么? NIO可以说是比BIO更强大的IO&#xff0c;可以设置非阻塞模式&#xff08;通过事件的方式监听数据的到来&#xff09; BIO是基于socket通信&#xff0c;一个线程对应一个socket连接&#xff0c;读取数据要一直等待 NIO是基于channel通信&#xff0c;一个线程管…

【动态规划】二分优化最长上升子序列

最长上升子序列 II 题解 题目传送门&#xff1a;AcWing 896. 最长上升子序列 II 一、题目描述 给定一个长度为 N 的数列&#xff0c;求数值严格单调递增的子序列的长度最长是多少。 输入格式&#xff1a; 第一行包含整数 N第二行包含 N 个整数&#xff0c;表示完整序列 输…

Dify接口api对接,流式接收流式返回(.net)

试了好多种方法除了Console.WriteLine()能打印出来&#xff0c;试了好些方法都不行&#xff0c;不是报错就是打印只有一行&#xff0c;要么就是接收完才返回...下面代码实现调用api接收流式数据&#xff0c;并进行流式返回给前端&#xff1a; using Furion.HttpRemote; using …

19-元素显示模式及浮动(CSS3)

知识目标 掌握标准文档流的解析规则掌握元素的显示模式掌握元素浮动属性语法与使用掌握浮动塌陷解决方法 1. 标准文档流 2. 元素显示模式 元素显示模式就是元素&#xff08;标签&#xff09;以什么方式进行显示&#xff0c;比如<div>独占一行&#xff0c;一行可以放多…

HTML jQuery 项目 PDF 批注插件库在线版 API 示例教程

本文章介绍 HTML && jQuery Web项目中 PDF 批注插件库 ElasticPDF 在线版 API 示例教程&#xff0c;API 包含 ① 导出批注后PDF数据&#xff1b;② 导出纯批注 json 数据&#xff1b;③ 加载旧批注&#xff1b;④ 切换文档&#xff1b;⑤ 切换用户&#xff1b;⑥ 清空批…

CATIA装配体全自动存储解决方案开发实战——基于递归算法的产品结构树批量处理技术

一、功能定位与技术架构 本工具针对CATIA V5装配体文件管理场景&#xff0c;实现了一套全自动递归存储系统&#xff0c;主要功能包括&#xff1a; ​智能路径选择&#xff1a;通过Tkinter目录对话框实现可视化路径选择​产品结构递归解析&#xff1a;深度优先遍历装配体中的子…

C#:接口(interface)

目录 接口的核心是什么&#xff1f; 1. 什么是接口&#xff08;Interface&#xff09;&#xff0c;为什么要用它&#xff1f; 2. 如何定义和使用接口&#xff1f; 3.什么是引用接口&#xff1f; 如何“引用接口”&#xff1f; “引用接口”的关键点 4. 接口与抽象类的区…

基于卷积神经网络CNN实现电力负荷多变量时序预测(PyTorch版)

前言 系列专栏:【深度学习:算法项目实战】✨︎ 涉及医疗健康、财经金融、商业零售、食品饮料、运动健身、交通运输、环境科学、社交媒体以及文本和图像处理等诸多领域,讨论了各种复杂的深度神经网络思想,如卷积神经网络、循环神经网络、生成对抗网络、门控循环单元、长短期记…

关于inode,dentry结合软链接及硬链接的实验

一、背景 在之前的博客 缺页异常导致的iowait打印出相关文件的绝对路径-CSDN博客 里 2.2.3 一节里&#xff0c;我们讲到了file&#xff0c;fd&#xff0c;inode&#xff0c;dentry&#xff0c;super_block这几个概念&#xff0c;在这篇博客里&#xff0c;我们针对inode和dentr…

游戏引擎学习第201天

仓库:https://gitee.com/mrxiao_com/2d_game_5 回顾之前的内容&#xff0c;并遇到了一次一阶异常&#xff08;First-Chance Exception&#xff09;。 欢迎来到新一期的开发过程&#xff0c;我们目前正在编写调试接口代码。 当前&#xff0c;我们已经在布局系统上进行了一些工…