蓝凌EKP产品:从 XML 到 JSON ——表单存储的性能优化实践
1. 背景介绍
蓝凌 EKP 的表单引擎,是整个低代码平台的核心能力之一。它不仅仅是“存储表单”,更是 企业级应用快速构建的基础设施。
它支持各种复杂表单配置(字段、布局、校验、权限、联动、子表单)。
它能灵活绑定流程,实现 表单 + 流程 + 权限 的一体化管控。
它为低代码应用提供了统一入口,业务人员通过拖拽和配置就能搭建应用,而无需写代码。
正是这种 强大、灵活、稳定 的能力,让我们的表单引擎能支撑上千种应用场景,从人事、财务、行政到项目、客户管理,真正成为企业数字化的核心引擎。
业务强大带来的新挑战
然而,随着业务场景越来越复杂,表单配置越来越灵活,表单数据存储的性能瓶颈也逐渐显现。
我们早期选择 XML 存储表单值,非常合理:它层次清晰、可扩展、可校验,能快速支撑表单配置和跨系统兼容。
但在今天,表单数量激增、字段量级庞大,XML 的 解析性能和存储冗余 成为用户体验的隐形负担。
为了让表单引擎在保持业务强大的同时,也能在性能上持续突破,我们开始探索 将存储方式从 XML 演进到 JSON。
为什么要转向 JSON?
更快:JSON 解析效率普遍高于 XML,能明显提升表单的加载速度。
更轻:JSON 格式更紧凑,占用存储空间更小。
更兼容:JSON 已经成为前后端交互的事实标准,更符合微服务和低代码平台的技术生态。
更灵活:数据库(如 MySQL、Postgres、OceanBase)原生支持 JSON 类型,后续还能直接做查询和索引。
这一转变,不是推翻 XML,而是顺应业务发展、技术迭代的 优化升级。
表单引擎已经足够强大,但强大也意味着要面对更高的性能挑战。选择从 XML 向 JSON 迁移,是我们在持续优化用户体验、提升系统性能道路上的又一次重要演进。
2. 问题分析
性能瓶颈:XML 解析开销大,DOM 需要完整装载,SAX 流式复杂。
存储冗余:XML 标签过长,大字段占用存储空间明显。
兼容性差:前后端交互大多倾向于 JSON,XML 转换额外耗时。
举例:某个大表单打
开耗时 2s+,主要在 XML 解析环节。
3. 技术对比:XML vs JSON
表格形式更直观:
维度 | XML | JSON |
---|---|---|
数据格式 | 标签结构 | 键值对结构 |
存储大小 | 冗余多,占用大 | 紧凑,节省空间 |
解析速度 | 慢(需逐层解析) | 快(轻量解析库) |
可读性 | 层次清晰 | 更简洁 |
Schema 约束 | 有 (XSD) | 弱(需额外方案) |
生态兼容 | 传统系统友好 | 前端 & 微服务友好 |
4. 优化方案设计
保留表单定义的层次化结构,但存储层改为 JSON。
数据库层:如果 DB 支持 JSON 类型,可以直接用 JSON 字段;否则用 TEXT 存 JSON 字符串。
应用层:使用 Jackson/Fastjson/Gson 替代 XML 解析器。
兼容方案:老表单继续用 XML,新增表单优先用 JSON。
5. 实践过程
贴代码示例:
XML 解析示例(原有实现)
将Map 表单集合转换为XML
public static String objectXmlEncoder(Object obj)throws FileNotFoundException, IOException, Exception {ByteArrayOutputStream baos = new ByteArrayOutputStream();XMLEncoder encoder = new XMLEncoder(baos);encoder.setPersistenceDelegate(BigDecimal.class,bigDecimalPersistenceDelegate);encoder.writeObject(obj);encoder.flush();encoder.close();String rtnVal = new String(baos.toByteArray(), "UTF-8");baos.close();return rtnVal;}
将XML 转换为Map 表单集合
String safeIns = ins.replaceAll("[\\x00-\\x08\\x0b-\\x0c\\x0e-\\x1f]", "");ByteArrayInputStream byteArrayInputStream = null;try{byteArrayInputStream = new ByteArrayInputStream(safeIns.getBytes("UTF-8"));//通过流读取转换成表单集合数据。return objectXmlDecoder(byteArrayInputStream);}finally{if(byteArrayInputStream!=null){byteArrayInputStream.close();}}
JSON 解析示例(优化后)
将Map 表单集合转换为XML
import com.fasterxml.jackson.databind.ObjectMapperprivate static ObjectMapper mapper = null;
static {mapper = new ObjectMapper();mapper.activateDefaultTyping(mapper.getPolymorphicTypeValidator(),ObjectMapper.DefaultTyping.NON_FINAL_AT_LEVEL,JsonTypeInfo.As.PROPERTY);
}//传入参数Map 集合 obj ,直接转换为xmlpublic static String objectJsonEncoder(Object obj) throws Exception{String string = mapper.writerWithDefaultPrettyPrinter().writeValueAsString(obj);return string;}
将XML 转换为Map 表单集合
//读取xml 转换为表单Map集合
public static Map objectJsonDecoder(String obj) throws Exception{Map datas = mapper.readValue(obj, HashMap.class);return datas;}
对比两段代码的简洁度。
为了考虑兼容性和提供给用户选择,提供了开关让用户选择xml 和json。
6. 性能对比实验
描述测试环境:JDK 版本、表单大小(如 500 字段)、数据库类型。
给出测试数据(例如:解析 1000 次表单的耗时对比)。
示例表格:
测试场景 | XML 解析耗时 | JSON 解析耗时 | 提升比例 |
---|---|---|---|
小表单(50 字段) | 120ms | 40ms | 3x |
大表单(500 字段) | 2100ms | 600ms | 3.5x |
7. 收益与思考
收益:表单打开速度更快,存储空间减少,系统响应更快。
不足:JSON 缺乏严格约束,需要额外校验。
未来:考虑进一步利用数据库 JSON 索引、缓存机制,提升查询效率。
8. 总结
XML 在早期合适,但随着系统演进,JSON 更适合高性能和前后端一体化。
从 XML 到 JSON 的迁移,带来了 性能优化 + 存储优化 + 技术栈统一 的价值。
希望本文的经验能为有类似困扰的开发者提供参考。