Redis发布订阅不校验消息类型,业务需自行约定序列化协议;Spring Boot中StringRedisTemplate默认仅处理字符串,发送对象需显式转JSON,接收端须指定UTF-8编码并捕获解析异常,跨语言需统一时间格式与序列化实现。

Redis发布订阅本身不支持消息类型校验
Redis的PUBLISH和SUBSCRIBE底层只认字节数组,它不管你是JSON、Protobuf还是纯字符串——发进去的是byte[],收出来也是byte[]。所谓“自定义消息类型”,其实是业务层通过序列化/反序列化约定出来的,Redis自己既不识别也不验证。
这意味着:如果你往redis_channel里发了一个{"name":"Alice"},又发了一个42(整数),再发一个0x01 0x02(二进制),Redis全盘照收,也全盘转发。订阅方拿到后,必须靠自己判断该用什么方式解码。
Spring Boot中用StringRedisTemplate默认只处理字符串
这是新手最容易踩的坑:直接用stringRedisTemplate.convertAndSend("topic", obj),结果obj是Student对象,发出去变成"com.example.Student@1a2b3c"这种toString结果,根本没法反序列化。
- 必须显式调用
JSONUtil.toJsonStr()或ObjectMapper.writeValueAsString()转成JSON字符串再发 - 接收端不能直接
new String(message.getBody())就完事——得先确认这串字节确实是UTF-8编码的JSON - 如果服务间协议要求强类型(比如前端只认
StudentEvent,拒绝UserEvent),就得在消息体里加type字段,由消费者做if ("student".equals(json.get("type")))分支判断
用MessageListener反序列化时要防空指针和格式异常
你看到的示例代码里这行:new String(message.getBody()),看似简单,其实藏着三个雷:
Redis 缓存和数据结构管理技能。通过自然语言操作 Redis,支持 String、Hash、List、Set、ZSet、Stream 等数据结构操作。当用户提到 Redis、缓存、消息队列、会话存储时使用此技能。
-
message.getBody()可能为null(极少见但Redis网络抖动时发生过) -
new String(...)没指定字符集,默认用系统编码,Linux和Windows可能不一致 → 建议写死new String(message.getBody(), StandardCharsets.UTF_8) - JSON解析失败时别让
onMessage方法抛出异常——Spring会静默吞掉错误,导致消息“消失”却无日志。务必包一层try-catch并打log.error
示例片段:
public void onMessage(Message message, byte[] pattern) {
try {
String body = new String(message.getBody(), StandardCharsets.UTF_8);
Student event = JSONUtil.toBean(body, Student.class);
log.info("收到学生事件:{}", event.getName());
} catch (Exception e) {
log.error("解析消息失败,channel={}, raw={}",
new String(message.getChannel()),
new String(message.getBody(), StandardCharsets.UTF_8), e);
}
}
跨语言场景下序列化协议必须对齐
Java服务发JSON,Go服务收JSON,看着没问题——但如果Java用fastjson,Go用encoding/json,遇到Date字段就可能一个输出"2026-04-01T05:30:00",另一个期待"2026-04-01 05:30:00",直接解析失败。
- 统一用ISO 8601格式(带T和Z)处理时间字段
- 避免用
Map<String, Object>这种泛型结构传参,改用明确定义的DTO类 - 如果要用二进制协议(如Protobuf),必须确保所有语言客户端都用同一份
.proto文件生成代码,且版本严格一致
最麻烦的不是序列化本身,而是某天Python脚本临时接入时,用json.dumps(dict, ensure_ascii=False)多加了个中文空格——这个空格会让Java的JSONUtil静默失败,而日志里只显示“空消息”。

















