一、場景痛點與解決方案
1. 問題背景
在 Excel 導入導出場景中,開發者常面臨以下問題:
- 數據可讀性差:數據庫存儲的字典值(如 1、true)直接導出時難以理解
- 雙向轉換復雜:導入時需將用戶輸入的標簽反向解析為存儲值
- 代碼侵入性強:硬編碼字典類型導致業務邏輯與字典管理耦合
2. 設計方案
二、核心實現解析
1. 注解驅動設計
代碼示例
@Data
public class ConfigRespVO {// 導出列聲明 + 字典類型綁定@ExcelProperty(value = "參數類型", converter = DictConvert.class)@DictFormat(DictTypeConstants.CONFIG_TYPE) private Integer type;
}
2. 雙向轉換流程
導出流程(值 → 標簽)
導入流程(標簽 → 值)
三、關鍵技術實現
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()); // 驗證轉換結果}
}