ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

声明式编程实战:JQuick-Excel 导入三大配置项深度拆解(映射/转换/校验)

声明式编程实战:JQuick-Excel 导入三大配置项深度拆解(映射/转换/校验) JQuick-Excel 导入三大配置项使用手册MAPPING / TRANSFORM / VALIDATION本手册专注讲解 jquick-excel 导入IMPORT WITH中最核心的三个配置项MAPPING字段映射、TRANSFORM数据转换、VALIDATION数据校验。所有语法与参数均基于源码校验示例统一采用 XML 声明式写法。目录1. 总览与执行顺序2. MAPPING — 字段映射2.1 作用与语法2.2 基础示例2.3 使用规则2.4 读取映射后的值3. TRANSFORM — 数据转换3.1 作用与语法3.2 变量与字面量3.3 内置转换函数3.4 实战示例3.5 TRANSFORM 与 MAPPING 的关系4. VALIDATION — 数据校验4.1 作用与语法4.2 校验目标类型4.3 规则通用结构4.4 校验规则完整参考4.4.1 通用规则4.4.2 字符串类规则4.4.3 数值类规则4.4.4 日期类规则4.4.5 其他规则4.5 多规则组合4.6 实战示例5. 三者协同使用6. 常见问题与避坑指南7. 扩展机制简介1. 总览与执行顺序三个配置项均写在IMPORT WITH语句中以逗号分隔书写顺序任意。但在实际执行导入时框架有固定的处理顺序① VALIDATION → ② MAPPING → ③ TRANSFORM (校验原始值) (表头重命名) (值转换)阶段作用对象说明① VALIDATION原始单元格值对 Excel 中尚未做任何处理的原始值进行校验校验失败立即抛异常终止导入② MAPPING表头列名将 Excel 表头列名重命名为目标字段名仅改名不改值③ TRANSFORM单元格值对已映射字段下的值执行转换函数改变实际值关键点VALIDATION 校验的是原始值TRANSFORM 转换的是校验通过后的值。若某字段需要先转换再校验请使用 TRANSFORM 完成转换并在程序中对转换结果做二次校验。源码位置JExcelImportHandler.java 的importData方法。2. MAPPING — 字段映射2.1 作用与语法MAPPING 用于将 Excel 表头中的原始列名映射为目标字段名只重命名不改变值。MAPPING { Excel原始列名: 目标字段名, ... }左值Excel 表头第 1 行中实际出现的列名字符串必须用引号包裹。右值导入结果JQuickRow中使用的字段名。未在 MAPPING 中出现的列保留原始表头列名作为字段名。2.2 基础示例excelnameimportMappingreturnClassjava.util.List![CDATA[ IMPORT WITH HEADERtrue, SHEETSheet1, MAPPING { 学号: no, 姓名: name, 性别: sex, 年龄: age, 出生日期: birthday } ]]/excel2.3 使用规则场景行为列名出现在 MAPPING 左值使用右值作为字段名列名未出现在 MAPPING保留原始列名作为字段名MAPPING 左值在 Excel 中不存在该映射被忽略不报错HEADERfalseMAPPING 不生效字段名按列字母A、B、C…生成MAPPING 是 TRANSFORM 字段引用的桥梁TRANSFORM 中的${字段名}必须使用MAPPING 映射后的目标字段名。2.4 读取映射后的值ListJQuickRowrowsservice.importExcel(1,2);for(JQuickRowrow:rows){// 使用映射后的字段名取值Stringno(String)row.get(no);// 来自学号列Stringname(String)row.get(name);// 来自姓名列}3. TRANSFORM — 数据转换3.1 作用与语法TRANSFORM 对读取到的单元格值执行转换函数改变实际值。转换函数基于 jquick-transform-function 提供的 226 内置方法并支持 SPI 自定义扩展。TRANSFORM { 字段名: 函数名(参数1, 参数2, ...) }左值必须是MAPPING 映射后的目标字段名。右值一个函数调用表达式。3.2 变量与字面量在转换函数的参数中可使用以下几种写法写法含义示例${字段名}引用当前行已映射的字段值${sex}${变量名}引用JContext中传入的外部变量${dict}字符串单引号包裹的字符串字面量yyyy-MM-dd数字数值字面量1布尔布尔字面量true传入外部变量示例MapString,ObjectsexMapnewHashMap();sexMap.put(男,1);sexMap.put(女,2);JContextcontextnewJContext();context.put(dict,sexMap);JQuickParseHandlerparsernewJQuickExcelImportXmlParseFactory(context,inputStream);3.3 内置转换函数jquick-excel 默认依赖jquick-transform-function无需额外引入。以下为常用函数分类概览完整列表请参考 官方仓库字典与翻译函数说明示例trans字典翻译按 key 查 value 替换trans(${dict},${sex})日期时间函数说明示例dateFormat日期格式化dateFormat(${birthday},yyyy-MM-dd)now当前日期时间now()formatDate格式化日期formatDate(${date},yyyy/MM/dd)parseDate解析日期字符串parseDate(${str},yyyy-MM-dd)addDays/addMonths/addYears日期增减addDays(${date},7)daysBetween/monthsBetween/yearsBetween计算日期差daysBetween(${start},${end})数学运算函数说明示例add/subtract/multiply/divide四则运算add(${age},1)abs/ceil/floor/round取整abs(${num})max/min/avg统计聚合max(${a},${b})pow/sqrt幂 / 根pow(${x},2)字符串函数说明示例concat拼接concat(${first},${last})substring/left/right/mid截取substring(${s},0,3)replace/replaceAll替换replace(${s},a,b)trim/toLower/toUpper去空格 / 大小写toUpper(${s})mask掩码脱敏mask(${idCard},6,14,*)业务方法函数说明示例idCardAge身份证号算年龄idCardAge(${idCard})idCardBirthday身份证号提取生日idCardBirthday(${idCard},yyyy-MM-dd)idCardGender身份证号取性别idCardGender(${idCard})idCardValidate校验身份证号idCardValidate(${idCard})phoneMask手机号脱敏phoneMask(${phone},3,4)phoneValidate校验手机号phoneValidate(${phone})emailMask邮箱脱敏emailMask(${email})条件与逻辑函数说明示例if条件判断if(${age}18,成年,未成年)coalesce返回第一个非空值coalesce(${a},${b},默认)defaultIfNull空值替换defaultIfNull(${remark},无)eq/ne/gt/lt比较eq(${status},1)类型转换函数说明示例toInt/toLong/toDouble转数字toInt(${str})toString/toBoolean转字符串 / 布尔toString(${num})3.4 实战示例字典翻译 日期格式化 数值运算excelnameimportTransformreturnClassjava.util.List![CDATA[ IMPORT WITH HEADERtrue, SHEETSheet1, MAPPING { 学号: no, 姓名: name, 性别: sex, 年龄: age, 出生日期: birthday, 身份证号: idCard, 手机号: phone }, TRANSFORM{ sex:trans(${dict},${sex}), birthday:dateFormat(${birthday},yyyy-MM-dd), age:add(${age},1), idCard:mask(${idCard},6,14,*), phone:phoneMask(${phone},3,4) } ]]/excel调用端传入字典MapString,ObjectsexMapnewHashMap();sexMap.put(男,1);sexMap.put(女,2);JContextcontextnewJContext();context.put(dict,sexMap);JQuickParseHandlerparsernewJQuickExcelImportXmlParseFactory(context,is);3.5 TRANSFORM 与 MAPPING 的关系TRANSFORM 的字段名引用必须是 MAPPING 映射后的目标字段名Excel 列 性别 ↓ MAPPING 字段名 sex ↓ TRANSFORM trans(${dict},${sex}) ← 这里用 ${sex}不是 ${性别}若 MAPPING 将 “性别” 映射为 “gender”则 TRANSFORM 应写gender:trans(${dict},${gender})。4. VALIDATION — 数据校验4.1 作用与语法VALIDATION 在导入数据前对原始单元格值进行校验校验失败立即抛出异常终止导入。VALIDATION { 目标区域: { 规则名{ required: true|false, msg: 错误消息, map: { 参数键: 参数值 } }, 规则名{ ... } // 同一区域可配多个规则逗号分隔 }, 目标区域: { ... } }重要VALIDATION 校验的是原始值未经 TRANSFORM 转换的值。例如性别列在 Excel 中是 “男”/“女”则校验时也按 “男”/“女” 校验而不是转换后的 “1”/“2”。4.2 校验目标类型VALIDATION 支持四种目标区域通过不同的语法指定类型语法说明示例行ROW N或ROW N..M校验某行或行范围ROW 5、ROW 1..10列COL X或COL X..Y校验某列或列范围COL A、COL A..D单元格XN校验单个单元格C2C 列第 2 行区域XN:YM校验矩形区域A1:B5列也可省略COL关键字直接写A或A..D。多目标校验示例excelnameimportMultiTargetreturnClassjava.util.List![CDATA[ IMPORT WITH VALIDATION{ ROW 2..10:{ required{required:true,msg:第2-10行不能为空} }, A..D:{ max_length{required:true,msg:列长度超限,map:{maxLength:50}} }, C2:{ regex{required:true,msg:格式不对,map:{pattern:^\\d$}} }, A1:B5:{ min_length{required:true,msg:长度不足,map:{minLength:2}} } } ]]/excel4.3 规则通用结构每条规则由三部分组成配置项类型是否必填说明requiredboolean是是否启用校验建议显式写true为false时跳过校验直接放行msgstring否自定义错误消息校验失败时抛出不填则使用规则默认消息mapobject视规则而定规则参数部分规则必填见下方各规则说明校验失败行为当required:true且校验不通过时框架抛出异常包含msg或默认消息终止整个导入流程。4.4 校验规则完整参考以下参数键均基于源码逐一校验map列标注无表示该规则不需要map参数。4.4.1 通用规则规则名map 参数参数类型说明示例required无—必填校验值不能为空required{required:true,msg:不能为空}4.4.2 字符串类规则规则名map 参数参数类型说明示例regexpatternString正则匹配regex{required:true,msg:只允许数字,map:{pattern:^\\d$}}max_lengthmaxLength数值最大长度max_length{required:true,msg:过长,map:{maxLength:7}}min_lengthminLength数值最小长度min_length{required:true,msg:过短,map:{minLength:1}}start_withstartWithString必须以 X 开头start_with{required:true,msg:必须以SO开头,map:{startWith:SO}}not_start_withnotStartWithString不能以 X 开头not_start_with{required:true,msg:非法前缀,map:{notStartWith:test}}end_withendWithString必须以 X 结尾end_with{required:true,msg:必须以有限公司结尾,map:{endWith:有限公司}}not_end_withnotEndWithString不能以 X 结尾not_end_with{required:true,msg:非法后缀,map:{notEndWith:test.com}}containcontainsString必须包含 Xcontain{required:true,msg:必须包含关键字,map:{contains:张三}}not_containnotContainString不能包含 Xnot_contain{required:true,msg:含敏感词,map:{notContain:敏感词}}注意参数键命名差异规则名用下划线start_with但参数键用驼峰startWith。contain的参数键是contains带 snot_contain的参数键是notContain不带 s。4.4.3 数值类规则规则名map 参数参数类型说明示例integer无—必须是整数integer{required:true,msg:必须是整数}decimal无—必须是小数decimal{required:true,msg:必须是小数}max_valuemaxValue数值不超过最大值max_value{required:true,msg:不能超过100,map:{maxValue:100}}min_valueminValue数值不小于最小值min_value{required:true,msg:不能小于0,map:{minValue:0}}4.4.4 日期类规则规则名map 参数参数类型说明示例date_formatformatString日期格式校验date_format{required:true,msg:格式错误,map:{format:yyyy-MM-dd}}max_dateformat,maxDateString, 日期不超过最大日期max_date{required:true,msg:超过最大日期,map:{format:yyyy-MM-dd,maxDate:2025-01-01}}min_dateformat,minDateString, 日期不早于最小日期min_date{required:true,msg:不能早于最小日期,map:{format:yyyy-MM-dd,minDate:2022-01-01}}日期字面量使用yyyy-MM-dd格式不需要引号如maxDate:2025-01-01。4.4.5 其他规则规则名map 参数参数类型说明示例email无—邮箱格式校验email{required:true,msg:邮箱格式错误}mobile无—中国大陆手机号^1[3-9]\d{9}$mobile{required:true,msg:手机号格式错误}dict键值对Map值必须存在于字典的值集合中dict{required:true,msg:性别非法,map:{1:男,2:女}}boolean键值对Map值必须存在于映射的值集合中boolean{required:true,msg:布尔值非法,map:{T:true,F:false}}composite无—组合规则容器编程式扩展用composite{}dict与boolean的特殊行为二者都是校验值是否在map的values中。例如dict{map:{1:男,2:女}}表示 Excel 单元格的值必须是男或女即 value而不是1/2即 key。4.5 多规则组合同一目标区域可配置多条规则以逗号分隔所有规则都会执行任一失败即抛异常excelnameimportMultiRulereturnClassjava.util.List![CDATA[ IMPORT WITH VALIDATION{ D2:D100:{ required{required:true,msg:年龄不能为空}, integer{required:true,msg:年龄必须是整数}, min_value{required:true,msg:年龄0,map:{minValue:0}}, max_value{required:true,msg:年龄150,map:{maxValue:150}} } } ]]/excel4.6 实战示例综合校验字符串 数值 日期 字典 邮箱 手机excelnameimportFullValidationreturnClassjava.util.List![CDATA[ IMPORT WITH HEADERtrue, SHEETSheet1, MAPPING { 姓名: name, 性别: sex, 年龄: age, 出生日期: birthday, 手机号: phone, 邮箱: email, 订单号: orderId }, VALIDATION{ B2:B1000:{ required{required:true,msg:姓名不能为空}, min_length{required:true,msg:姓名至少2位,map:{minLength:2}}, max_length{required:true,msg:姓名最长10位,map:{maxLength:10}} }, C2:C1000:{ dict{required:true,msg:性别非法,map:{1:男,2:女}} }, D2:D1000:{ integer{required:true,msg:年龄必须是整数}, min_value{required:true,msg:年龄6,map:{minValue:6}}, max_value{required:true,msg:年龄60,map:{maxValue:60}} }, E2:E1000:{ date_format{required:true,msg:日期格式错误,map:{format:yyyy-MM-dd}}, min_date{required:true,msg:不能早于2000年,map:{format:yyyy-MM-dd,minDate:2000-01-01}}, max_date{required:true,msg:不能晚于2025年,map:{format:yyyy-MM-dd,maxDate:2025-12-31}} }, F2:F1000:{ mobile{required:true,msg:手机号格式错误} }, G2:G1000:{ email{required:true,msg:邮箱格式错误} }, A2:A1000:{ start_with{required:true,msg:订单号必须以SO开头,map:{startWith:SO}} } } ]]/excel5. 三者协同使用一个完整的导入配置通常同时使用三者excelnameimportStudentFullreturnClassjava.util.List![CDATA[ IMPORT WITH HEADERtrue, SHEET学生表, MAPPING { 学号: no, 姓名: name, 性别: sex, 年龄: age, 出生日期: birthday }, TRANSFORM{ sex:trans(${dict},${sex}), birthday:dateFormat(${birthday},yyyy-MM-dd), age:add(${age},1) }, VALIDATION{ C2:C1000:{ dict{required:true,msg:性别非法,map:{1:男,2:女}} }, D2:D1000:{ integer{required:true,msg:年龄必须是整数}, min_value{required:true,msg:年龄0,map:{minValue:0}} }, E2:E1000:{ date_format{required:true,msg:日期格式错误,map:{format:yyyy-MM-dd}} } } ]]/excel完整处理流程示例以性别列为例Excel 单元格值: 男 ↓ ① VALIDATION校验原始值 男 dict{map:{1:男,2:女}} → 男 在 values 中 → ✅ 通过 ↓ ② MAPPING表头重命名 性别 → sex ↓ ③ TRANSFORM值转换 trans(${dict},${sex}) → 查字典 ${dict}[男] 1 ↓ 最终结果 JQuickRow.get(sex) 16. 常见问题与避坑指南6.1 VALIDATION 校验的是原始值还是转换后的值原始值。VALIDATION 在 TRANSFORM 之前执行校验的是 Excel 中的原始单元格值。若 Excel 中性别列是 “男”/“女”校验时按 “男”/“女” 校验而非转换后的 “1”/“2”。6.2 TRANSFORM 中的字段名该写哪个写MAPPING 映射后的目标字段名。若 MAPPING 将 “性别” 映射为 “sex”则 TRANSFORM 应写sex:trans(${dict},${sex})而非性别:...。6.3 dict / boolean 规则的 map 是按 key 还是 value 校验按value校验。dict{map:{1:男,2:女}}表示单元格值必须是男或女。6.4 日期字面量需要加引号吗不需要。maxDate:2025-01-01直接写日期字面量不要写成2025-01-01。6.5 required 配置项有什么作用required:true—— 启用该校验规则。required:false—— 跳过校验直接放行即使值为空或不符合规则。注意这并非字段是否必填的语义。要校验字段非空请使用required规则required{required:true,msg:不能为空}而非把别的规则的required设为 true。6.6 规则名与参数键的命名风格为什么不一致规则名使用下划线如start_with、max_length参数键使用驼峰如startWith、maxLength。这是框架的既定约定配置时请严格对照本手册的参数表。6.7 校验失败后会怎样校验失败会抛出异常包含msg自定义消息或规则默认消息终止整个导入流程已读取的数据不会返回。若希望容错请在调用端 try-catch 处理。7. 扩展机制简介7.1 自定义转换函数TRANSFORMTRANSFORM 的函数基于 SPI 机制扩展详见 jquick-transform-function。核心步骤实现JQuickMethodFunctionProvider接口或继承JQuickBaseFunctionFunctionProvider。在META-INF/services/com.github.paohaijiao.function.core.JQuickMethodFunctionProvider注册实现类。在 XML 的 TRANSFORM 中按getMethodName()调用。也支持运行时动态注册JQuickMethodInvocationManagermanagerJQuickMethodInvocationManager.getInstance();manager.registerInvoker(myFunc,(args)-{// 自定义逻辑returnresult;},自定义函数说明);7.2 自定义校验规则VALIDATIONVALIDATION 支持自定义规则扩展继承JAbstractValidationRule实现doValidate(String value)和getDefaultMsg()。在JMethodValidationRuleType枚举中注册MY_RULE(my_rule, JMyRule.class)。在JExcelValidationRuleFactory增加工厂方法。在 XML 中使用my_rule{required:true,msg:校验失败}。完整的 SPI 扩展说明请参考 useage-import.md 第 4 章。更多用法可参考README.md 使用示例章节useage-import.md 完整导入使用手册测试用例src/test/java/com/github/paohaijiao/importFile/validate/
返回列表