You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Spring Redis Pub/Sub:onMessage中message.getBody()转字符串出现乱码

Redis订阅消息乱码/出现额外字符问题排查

问题场景

实现Redis的MessageListener接口自定义订阅者RedisSubscriber,重写onMessage方法的代码如下:

@Override
public void onMessage(Message message, byte[] pattern) {

    messageList.add(message.getBody().toString());

    System.out.println("Message received: " + new String(message.getBody(), StandardCharsets.UTF_8));

}

控制台输出异常,出现额外乱码字符:Message received: �� t Hi test,反序列化也无法正常转换。

原因分析

  • 序列化方式不匹配:如果发送端使用RedisTemplate默认的JdkSerializationRedisSerializer序列化消息,字节流中会包含类元数据等额外信息,并非纯UTF-8字符串的字节数组,接收端直接用UTF-8解码就会出现乱码。
  • 字节数组toString()用法错误:直接调用message.getBody().toString()得到的是字节数组的内存地址标识(格式类似[B@xxxxxx),而非实际字符串内容,会导致列表中存入无效数据。

解决方案

方案1:统一使用字符串序列化器

确保发送端和接收端序列化逻辑一致,推荐使用StringRedisSerializer处理字符串消息:

发送端RedisTemplate配置

@Bean
public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory factory) {
    RedisTemplate<String, Object> template = new RedisTemplate<>();
    template.setConnectionFactory(factory);
    StringRedisSerializer stringSerializer = new StringRedisSerializer();
    // 统一设置key和value的序列化器
    template.setKeySerializer(stringSerializer);
    template.setValueSerializer(stringSerializer);
    template.setHashKeySerializer(stringSerializer);
    template.setHashValueSerializer(stringSerializer);
    template.afterPropertiesSet();
    return template;
}

接收端修正代码

此时message.getBody()是纯UTF-8字符串的字节数组,直接解码即可:

@Override
public void onMessage(Message message, byte[] pattern) {
    String content = new String(message.getBody(), StandardCharsets.UTF_8);
    messageList.add(content);
    System.out.println("Message received: " + content);
}

方案2:匹配发送端的JDK序列化逻辑

如果发送端必须使用JDK序列化,接收端需对应反序列化:

@Override
public void onMessage(Message message, byte[] pattern) {
    try (ObjectInputStream ois = new ObjectInputStream(new ByteArrayInputStream(message.getBody()))) {
        String content = (String) ois.readObject();
        messageList.add(content);
        System.out.println("Message received: " + content);
    } catch (IOException | ClassNotFoundException e) {
        e.printStackTrace();
    }
}

注意:发送的消息对象必须实现Serializable接口。

内容的提问来源于stack exchange,提问作者Kanika

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.09 07:40:33