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
相关产品推荐
相关产品推荐

