• RedisTemplate出现\xac\xed\x00\x05t\x00\x0f前缀解决


    问题描叙

    出现这种乱码前缀的原因是没有进行序列化,因此导致在传输过程出现乱码问题,存到数据库,发现 key,hash key/value 都有 \xAC\xED\x00\x05t\x00 前缀。RedisTemplate类中默认是没有设置序列化的。

    解决方法

    设置RedisTemplate的序列化方式

    1. import com.fasterxml.jackson.annotation.JsonAutoDetect;
    2. import com.fasterxml.jackson.annotation.PropertyAccessor;
    3. import com.fasterxml.jackson.databind.ObjectMapper;
    4. import org.springframework.context.annotation.Bean;
    5. import org.springframework.data.redis.connection.RedisConnectionFactory;
    6. import org.springframework.data.redis.core.RedisTemplate;
    7. import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
    8. import org.springframework.data.redis.serializer.StringRedisSerializer;
    9. public class RedisConfig {
    10. @Bean(name = "redisTemplate")
    11. //配置redisTemplate
    12. //默认情况下redisTemplate只能支持redisTemplate<String,String>
    13. //需要自定义 RedisTemplate,设置序列化
    14. public RedisTemplate<String,Object> redisTemplate(RedisConnectionFactory factory){
    15. RedisTemplate<String,Object> template = new RedisTemplate <>();
    16. template.setConnectionFactory(factory);
    17. Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class);
    18. ObjectMapper om = new ObjectMapper();
    19. om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
    20. om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
    21. jackson2JsonRedisSerializer.setObjectMapper(om);
    22. StringRedisSerializer stringRedisSerializer = new StringRedisSerializer();
    23. // key采用String的序列化方式
    24. template.setKeySerializer(stringRedisSerializer);
    25. // hash的key也采用String的序列化方式
    26. template.setHashKeySerializer(stringRedisSerializer);
    27. // value序列化方式采用jackson
    28. template.setValueSerializer(jackson2JsonRedisSerializer);
    29. // hash的value序列化方式采用jackson
    30. template.setHashValueSerializer(jackson2JsonRedisSerializer);
    31. template.afterPropertiesSet();
    32. return template;
    33. }
    34. }

    注意:用了StringRedisSerializer之后,redis库的数据都是以String类型保存,所以int类型的整数,在保存时,会类型上升, 先变成double,然后再存成String,也就是1会存成"1.0",所以如果保存int数据时,需要自己在代码中单独处理下。上面修改全局配置不能兼容新老数据,新增配置可以兼容。

    修改序列化方式后,数据不兼容报错

    org.springframework.data.redis.serializer.SerializationException: Cannot deserialize; nested exception is org.springframework.core.serializer.support.SerializationFailedException: Failed to deserialize payload. Is the byte array a result of corresponding serialization for DefaultDeserializer?; nested exception is java.io.StreamCorruptedException: invalid stream header: E5A487E6

    使用多个redisTemplate配置

    1. @Configuration
    2. public class RedisConfig {
    3. @Bean
    4. @Primary
    5. public RedisTemplate redisTemplate(RedisConnectionFactory connectionFactory) {
    6. RedisTemplate redisTemplate = new RedisTemplate<>();
    7. redisTemplate.setConnectionFactory(connectionFactory);
    8. redisTemplate.setKeySerializer(new StringRedisSerializer());
    9. redisTemplate.setValueSerializer(new StringRedisSerializer());
    10. redisTemplate.setHashKeySerializer(new StringRedisSerializer());
    11. redisTemplate.setHashValueSerializer(new StringRedisSerializer());
    12. return redisTemplate;
    13. }
    14. @Bean(name = "ByteRedisTemplate")
    15. public RedisTemplate ByteRedisTemplate(
    16. RedisConnectionFactory redisConnectionFactory) {
    17. RedisTemplate<String, Object> redisTemplate = new RedisTemplate<>();
    18. redisTemplate.setConnectionFactory(redisConnectionFactory);
    19. redisTemplate.setKeySerializer(new StringRedisSerializer());
    20. redisTemplate.setValueSerializer(RedisSerializer.byteArray());
    21. redisTemplate.setHashKeySerializer(new StringRedisSerializer());
    22. redisTemplate.setHashValueSerializer(RedisSerializer.byteArray());
    23. return redisTemplate;
    24. }
    25. }

    使用方法 

    1. @RestController
    2. public class PublishDemo {
    3. @Autowired
    4. private RedisTemplate redisTemplate;
    5. @Autowired
    6. @Qualifier("ByteRedisTemplate")
    7. private RedisTemplate byteRedisTemplate;
    8. @RequestMapping("set")
    9. public void set() {
    10. String key1 = "t1";
    11. String value = "12345";
    12. String key2 = "t2";
    13. String value2 = "54321";
    14. redisTemplate.opsForValue().set(key1, value);
    15. byteRedisTemplate.opsForValue().set(key2, value2.getBytes());
    16. }
    17. @RequestMapping("get")
    18. public void get() {
    19. Object t1 = redisTemplate.opsForValue().get("t1");
    20. System.out.println("t1:" + t1.toString());
    21. Object o = byteRedisTemplate.opsForValue().get("t2");
    22. System.out.println("t2:" + Arrays.toString((byte[]) o));
    23. }
    24. }

    对象存hash

    entityMap.forEach((field, value) -> redisTemplate.opsForHash().put(String.format(REDIS_CONN_KEY, entity.getId()), field, value != null ? String.valueOf(value) : ""));

    redis判断连接状态,重连机制

    1. if (!isset($this->redis) || !$this->redis->isConnected()) {
    2. $this->setRedis();
    3. }
    4. $this->redis->exists($key);
    5. /**
    6. * 连接redis.
    7. */
    8. private function setRedis()
    9. {
    10. if (isset($this->redis) && $this->redis->isConnected()) {
    11. $this->redis->disconnect();
    12. }
    13. $this->redis = new RedisClient($this->container->getParameter('redis_mq')); //重连redis;
    14. }

  • 相关阅读:
    MySQL索引
    6、Java——三种方式循环出水仙花数
    Python 提高篇学习笔记(一):深拷贝和浅拷贝
    微服务系列之单体架构
    猿创征文|瑞吉外卖——管理端_过滤器
    用户画像浅析
    快解析内网穿透为文档加密行业保驾护航
    计算机视觉: 可控的高质量人体生成
    C++笔记之尾置返回类型(trailing return type)
    怎么文字转语音?两分钟让你学会三种方法
  • 原文地址:https://blog.csdn.net/hudeyong926/article/details/133267963