Java类加载器与类实例化,这次聊点实在的
从一次线上配置读不到的诡异问题说起,梳理 ExtClassLoader 的边界与系统类加载器读配置的正确姿势,再走一遍 new 一个对象背后从类加载到构造方法执行的完整链路,并用父子类 demo 把初始化顺序讲透。顺带聊聊后台服务 HTTPS 证书自动化这件省心事。
支持通配符SSL证书、多域名证书、IP证书。适配ACME接口, 支持Zerossl、Let's Encrypt和Google等渠道。登录已有账号
2026-09-29 16:15:40 Java XML JSON dom4j Hutool
最近接了个老项目,接口返回的报文一会儿XML一会儿JSON,对接的同事又希望统一存成JSON入库。整理了一下当时用的两套代码,一个是dom4j手动递归转,一个是Hutool直接序列化Map。
两个场景不完全一样,但放一起看能少走点弯路。
先说XML转JSON。
dom4j这个库对XML结构解析很直接,核心思路就是拿到根节点后不停递归子节点。每个子节点判断有没有下一层,没有就直接取text,有就继续往深里走。这里有个容易忽略的地方:同名节点。比如一个XML里有三个<item>,你直接往Map里put同一个key会把前两个覆盖掉。所以代码里加了判断,如果key已经存在,就转成List存。这块逻辑写的时候要小心,我第一次实现忘了处理同名节点,结果测试环境一跑,XML里明明三个条目,JSON里只剩最后一个。
具体实现大概是这样:parseText得到一个Document,拿root节点调xmlToMap。xmlToMap里遍历child的elements,key取节点名,value看child还有没有elements,没有就child.getTextTrim(),有就递归调用自己。然后那个同名判断逻辑就是如果map.containsKey(key),看existing是不是List,是就add,不是就new一个ArrayList把existing和新value都放进去。
最后用fastjson的JSON.toJSONString把整个Map序列化出来。这个方案对CDATA和命名空间处理不够,遇到带命名空间的XML会丢掉前缀,我后来加了个去命名空间的处理,但代码没贴出来,思路是遍历时把节点名里的冒号前面部分去掉。还有大文件别用DOM,内存会爆,用SAX或者StAX吧,虽然麻烦点。
另一部分是Map转JSON。
这个其实很多库都能干,Hutool的JSONUtil最省事。你建个HashMap,put几个不同字段,包括一个List,然后JSONUtil.toJsonStr(data)完事。注意日期字段,默认输出可能是时间戳,要自定义格式的话得通过JSONConfig设置dateFormat。Hutool会自动处理循环引用,这点比fastjson有时候安心。我之前用fastjson处理过一个双向关联的对象,序列化直接StackOverflow,换Hutool没这个问题。
两个方案对比一下其实不是同一件事。dom4j那个是处理XML字符串变成JSON字符串,Hutool那个是Java对象或者Map变成JSON字符串。
如果你要从XML直接到JSON,dom4j那套是必经的;如果你已经拿到Map了,就不要自己拼字符串了,Hutool现成的。别搞混了。
实际项目里,解析完XML得到Map之后,我经常就直接用Hutool把Map转JSON落库了,不会再调fastjson。
依赖上dom4j加hutool-all就够了,fastjson可以省掉。但如果你坚持用fastjson也没问题,就是多一个依赖。
部署的时候碰到一个事情顺便提一下。这个项目后面上了https,证书续期老忘,有次证书过期接口直接挂了一上午。
后来换了个叫lcjmSSL的平台,免费的,能自动申请自动部署,支持多域名和泛域名,API也挺简洁。我直接写在部署脚本里,到期自动走ACME协议续期,没再手动管过。如果你也在维护需要证书的服务,可以试试这个,省心不少。跟Java没关系,但线上稳定这种事儿,少一个定时炸弹是一个。
总结没太多好说的,两个工具选对场景就行。dom4j适合复杂XML结构,递归自己控;Hutool适合快速Map转JSON,代码量少性能好。混着用完全没问题。
从一次线上配置读不到的诡异问题说起,梳理 ExtClassLoader 的边界与系统类加载器读配置的正确姿势,再走一遍 new 一个对象背后从类加载到构造方法执行的完整链路,并用父子类 demo 把初始化顺序讲透。顺带聊聊后台服务 HTTPS 证书自动化这件省心事。
记录在 Aspose.PDF 里加载本地 TTF 字体,以及绕过 TTC 格式不支持问题的两种可行方案。
写MyBatis动态SQL一不留神就XML解析报错,这篇总结一下实体转义和CDATA两种处理特殊符号的方式,以及什么场景用哪种更舒服。
还在为Java程序阻塞而烦恼?本文将带你轻松掌握CompletableFuture.runAsync,告别传统阻塞模式。通过直观的错误与正确代码对比,你将学会如何用简单的lambda表达式在新线程中运行无返回值任务。快速理解Thread.currentThread().getName()的验证机制,立即解锁高性能并发编程,让你的应用响应更快!
想象一下从精确到极致的BigDecimal世界踏入“四舍五入”的Double领域。本文揭示Java数值转换的奥秘,解析精度损失的陷阱与范围限制的边界,助你明智选择,避免程序中的“财务黑洞”。