应使用message.getbody()配合utf-8解码获取json字符串,而非message.tostring();必须统一发送端与监听端的redisserializer.json(),并确保userdto含public无参构造器和getter/setter。

直接用 RedisSerializer.json() 配合 MessageListener 就能传 JSON,但反序列化失败、类型丢失、空指针或乱码,基本都是序列化器没对齐或消息体没正确解包导致的。
为什么 message.toString() 会丢数据或报错
Redis 的 Message 对象里,真实内容在 message.getBody() 字节数组中;toString() 是调用字节数组的默认实现(类似 [B@1a2b3c),不是 JSON 字符串。硬转会导致解析失败或空对象。
- 错误写法:
new String(message.toString())或JSONObject.parseObject(message.toString(), UserDTO.class) - 正确做法:先用
new String(message.getBody(), StandardCharsets.UTF_8)提取原始 JSON 字符串 - 如果用了
RedisSerializer.json(),且发送端是redisTemplate.convertAndSend(),那getBody()就是标准 UTF-8 JSON 字节流,无需额外解码
RedisSerializer.json() 和 RedisSerializer.java() 怎么选
传 JSON 就必须用 RedisSerializer.json(),否则接收端拿到的是 JDK 序列化二进制,根本不是可读 JSON,JSON.parseObject() 会直接抛 JSONException 或乱码。
-
RedisSerializer.json():依赖 Fastjson2 / Jackson,序列化后是紧凑可读字符串,跨语言友好,推荐用于结构化消息 -
RedisSerializer.java():JDK 原生序列化,要求类实现Serializable,体积大、不兼容其他语言、有安全风险,仅适合纯 Java 内部临时通信 - 发送端和监听端的
serializer必须一致——container.addMessageListener(...)里设的setSerializer()要和redisTemplate的序列化器匹配
反序列化时如何避免 ClassCastException 或 null 字段
Spring Data Redis 的 MessageListenerAdapter 在启用 RedisSerializer.json() 后,其实已能自动把 JSON 反序列化为指定类型(前提是配置了泛型信息)。手动解析反而容易出错。
- 推荐方式:让
MessageListenerAdapter直接注入目标类型参数,例如onMessage(UserDTO userDTO)(方法签名带具体类型) - 不推荐方式:在
onMessage(Message, byte[])里手动JSON.parseObject(...)——容易漏处理空值、时区、枚举等细节 - 若必须手动解析,用
JSON.parseObject(new String(msg.getBody()), UserDTO.class),别用message.toString() - 注意:Fastjson2 默认不支持无参构造器缺失或字段非 public 的类,反序列化前确认
UserDTO有 public 无参构造 + getter/setter
多个监听器混用不同序列化器会怎样
可以,但每个 MessageListenerAdapter 必须单独设置 setSerializer(),且不能共享同一个 adapter 实例。否则后注册的会覆盖前者的序列化行为。
- 错误示范:两个 listener 共用一个
MessageListenerAdapter实例,只调一次setSerializer() - 正确做法:像知识库示例那样,为
listenerAdapter和listenerAdapter2分别 new 并各自setSerializer() - 后果:混用时,某监听器收到非预期格式(比如 JSON 字节被当 JDK 二进制解析),大概率抛
StreamCorruptedException或返回 null 对象
最易忽略的一点:RedisSerializer.json() 默认使用 Fastjson2,但 Spring Boot 3+ 默认可能用 Jackson;如果项目里没显式声明 Fastjson2 依赖,又没配 Jackson 的 ObjectMapper,convertAndSend() 可能静默失败或序列化成空对象——务必检查实际序列化输出是否为合法 JSON 字符串。











