Event Bus 不能直接发送大 XML 文件内容,仅支持轻量数据如 JsonObject;应上传后发元数据(如 taskId、storagePath),下游按需安全读取并解析,禁用 XXE,超大文件需流式处理,推荐 publish() 实现多消费者协作。

Event Bus 能不能直接发 XML 文件内容
不能。Vert.x 的 eventBus.send() 和 eventBus.publish() 只支持可序列化的 POJO、JsonObject、JsonArray、基本类型及它们的数组。原始 XML 字符串(如 String)可以发,但大文件(比如几 MB 的 XML)直接转成 String 或 Buffer 再塞进消息体,会触发堆内存暴涨甚至 OutOfMemoryError,而且违背事件总线“轻量通信”的设计定位。
上传阶段如何把 XML 任务交给 Event Bus
正确做法是:上传完成后,把任务元数据(而非 XML 本体)发到总线。下游消费者收到后,再按需读取文件或从存储加载 XML。常见组合方式:
- 上传接口(如
Router.post("/upload"))接收MultipartForm,将 XML 保存到本地临时目录或对象存储(如 MinIO),返回唯一taskId - 构造轻量消息:用
JsonObject封装taskId、fileName、storagePath、timestamp等字段 - 调用
eventBus.publish("xml.task.ready", message)—— 注意用publish()实现广播,多个处理器可同时响应
JsonObject taskMsg = new JsonObject()
.put("taskId", "task-7f3a9b")
.put("storagePath", "/tmp/uploads/report_2024.xml")
.put("contentType", "application/xml")
.put("uploadedAt", System.currentTimeMillis());
eventBus.publish("xml.task.ready", taskMsg);
下游服务怎么安全读取并解析 XML
监听端不能假设 XML 一定在本地磁盘;必须检查路径是否存在、是否有读权限,并设置超时和大小限制。尤其注意 SAX/DOM 解析器的外部实体(XXE)风险:
特色介绍: 1、ASP+XML+XSLT开发,代码、界面、样式全分离,可快速开发 2、支持语言包,支持多模板,ASP文件中无任何HTML or 中文 3、无限级分类,无限级菜单,自由排序 4、自定义版头(用于不规则页面) 5、自动查找无用的上传文件与空目录,并有回收站,可删除、还原、永久删除 6、增强的Cache管理,可单独管理单个Cache 7、以内存和XML做为Cache,兼顾性能与消耗 8、
- 禁用外部 DTD:对
DocumentBuilderFactory设置setFeature("http://apache.org/xml/features/disallow-doctype-decl", true) - 避免用
new XmlParser()(Vert.x Web Client 自带的)直接解析未校验的原始输入 - 推荐先用
FileSystem.readFile()读取为Buffer,再传给白名单校验后的 SAX 解析器 - 若 XML 超过 10MB,考虑流式解析(
XMLStreamReader)+ 拆分处理,别一次性 load 到内存
为什么不用点对点 send() 而用 publish()
上传任务常需多消费者协作:一个校验格式,一个提取关键字段入库,一个触发通知。用 send() 只能指定单个地址,扩展性差;而 publish() 天然支持一对多,且各消费者可独立部署、重启,不互相阻塞。但要注意:
-
publish()不保证送达(无应答机制),关键任务需配合持久化队列(如 Kafka)或业务层 ACK - 所有监听者必须用相同地址字符串(如
"xml.task.ready"),拼写错误会导致静默丢消息 - 若某消费者处理慢,Event Bus 默认不背压 —— 需在 handler 内手动控制并发(例如用
ExecutorService限流)









