默认的Jackson2JsonMessageConverter因启用DefaultTyping而写入类全限定名,反序列化时若消费者端缺失该类即抛ClassNotFoundException;解决需两步:禁用DefaultTyping并显式设置setDefaultType或使用白名单类型映射。

为什么默认的 Jackson2JsonMessageConverter 会抛 ClassNotFoundException?
因为 Spring AMQP 的 Jackson2JsonMessageConverter 默认启用 DefaultTyping(即在 JSON 中写入类的全限定名),反序列化时会尝试加载那个类——如果消费者端没有该 class,就直接报 ClassNotFoundException。这不是 bug,是设计使然,但生产环境几乎总是要关掉它。
如何安全关闭类型信息写入并指定目标类型?
别只调 setClassMapper() 或改 ObjectMapper,关键在两步:禁用默认类型信息 + 显式绑定接收类型。否则即使 JSON 看起来正常,MessageListener 可能收到 LinkedHashMap 而不是你的 POJO。
- 创建
ObjectMapper时调用disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS)和disable(DefaultTyping.NON_FINAL)(或更彻底地用activateDefaultTyping(..., As.WRAPPER_ARRAY)配合白名单) - 在
Jackson2JsonMessageConverter上设置setDefaultType(Class<?>),比如converter.setDefaultType(MyEvent.class) - 若需多类型支持,用
SimpleTypeMapper并注册typePrecedence映射关系,避免依赖消息头里的_class
MessageProperties.setContentType() 必须设为 "application/json" 吗?
必须。RabbitMQ 本身不校验 content-type,但 Jackson2JsonMessageConverter 在 fromMessage() 里会检查 messageProperties.getContentType() 是否匹配 "application/json"(忽略大小写)。如果发消息时没设、或设成 "text/plain",转换器会跳过反序列化,直接返回原始字节数组。
DMap GL地图JSAPI(dmapgl)开发指南。用于编写、审查、调试 DMap 地图 API 代码,涵盖地图初始化、覆盖物渲染、图层管理、事件处理、控件交互等任务。当用户提及 dmap、dmapgl、jsapi‑gl 或相关地图开发需求时自动触发。
- 发送方:用
convertAndSend(exchange, routingKey, obj, message -> { message.getMessageProperties().setContentType("application/json"); return message; }) - 接收方:确保容器工厂的
setMessageConverter()已设为你自定义的 converter - 调试时可打印
message.getMessageProperties().getContentType()确认值
自定义 converter 后,Spring Boot 的自动配置还生效吗?
只要你在 @Configuration 类里声明了 @Bean 类型为 MessageConverter 的 bean,Spring Boot 的 RabbitAutoConfiguration 就会跳过默认的 Jackson2JsonMessageConverter 创建逻辑。但注意:这个 bean 必须是顶层 @Bean 方法返回,不能包在 @ConditionalOnMissingBean 里再手动 new —— 否则可能和 auto-configuration 冲突导致两个 converter 共存。
立即学习“Java免费学习笔记(深入)”;
最容易被忽略的是:自定义 converter 没有显式 set ObjectMapper 时,它会 fallback 到 Spring Boot 的 Jackson2ObjectMapperBuilder 实例,而该实例默认仍开启 DefaultTyping。所以哪怕你写了自定义 bean,也得亲手 disable 掉。

















