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

问题描叙

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

解决方法

设置RedisTemplate的序列化方式

复制代码
import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.context.annotation.Bean;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;
 
public class RedisConfig {
    @Bean(name = "redisTemplate")
    //配置redisTemplate
    //默认情况下redisTemplate只能支持redisTemplate<String,String>
    //需要自定义 RedisTemplate,设置序列化
    public RedisTemplate<String,Object> redisTemplate(RedisConnectionFactory factory){
        RedisTemplate<String,Object> template = new RedisTemplate <>();
        template.setConnectionFactory(factory);
 
        Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class);
        ObjectMapper om = new ObjectMapper();
        om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
        om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
        jackson2JsonRedisSerializer.setObjectMapper(om);
 
        StringRedisSerializer stringRedisSerializer = new StringRedisSerializer();
        // key采用String的序列化方式
        template.setKeySerializer(stringRedisSerializer);
        // hash的key也采用String的序列化方式
        template.setHashKeySerializer(stringRedisSerializer);
        // value序列化方式采用jackson
        template.setValueSerializer(jackson2JsonRedisSerializer);
        // hash的value序列化方式采用jackson
        template.setHashValueSerializer(jackson2JsonRedisSerializer);
        template.afterPropertiesSet();
        return template;
    }
}

注意:用了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配置

复制代码
@Configuration
public class RedisConfig {

    @Bean
    @Primary
    public RedisTemplate redisTemplate(RedisConnectionFactory connectionFactory) {
        RedisTemplate redisTemplate = new RedisTemplate<>();
        redisTemplate.setConnectionFactory(connectionFactory);
        redisTemplate.setKeySerializer(new StringRedisSerializer());
        redisTemplate.setValueSerializer(new StringRedisSerializer());
        redisTemplate.setHashKeySerializer(new StringRedisSerializer());
        redisTemplate.setHashValueSerializer(new StringRedisSerializer());
        return redisTemplate;
    }

    @Bean(name = "ByteRedisTemplate")
    public RedisTemplate ByteRedisTemplate(
            RedisConnectionFactory redisConnectionFactory) {
        RedisTemplate<String, Object> redisTemplate = new RedisTemplate<>();
        redisTemplate.setConnectionFactory(redisConnectionFactory);
        redisTemplate.setKeySerializer(new StringRedisSerializer());
        redisTemplate.setValueSerializer(RedisSerializer.byteArray());
        redisTemplate.setHashKeySerializer(new StringRedisSerializer());
        redisTemplate.setHashValueSerializer(RedisSerializer.byteArray());
        return redisTemplate;
    }
}

使用方法

复制代码
@RestController
public class PublishDemo {

    @Autowired
    private RedisTemplate redisTemplate;

    @Autowired
    @Qualifier("ByteRedisTemplate")
    private RedisTemplate byteRedisTemplate;

    @RequestMapping("set")
    public void set() {
        String key1 = "t1";
        String value = "12345";
        String key2 = "t2";
        String value2 = "54321";
        redisTemplate.opsForValue().set(key1, value);
        byteRedisTemplate.opsForValue().set(key2, value2.getBytes());
    }

    @RequestMapping("get")
    public void get() {
        Object t1 = redisTemplate.opsForValue().get("t1");
        System.out.println("t1:" + t1.toString());
        Object o = byteRedisTemplate.opsForValue().get("t2");
        System.out.println("t2:" + Arrays.toString((byte[]) o));
    }
}

对象存hash

复制代码
entityMap.forEach((field, value) -> redisTemplate.opsForHash().put(String.format(REDIS_CONN_KEY, entity.getId()), field, value != null ? String.valueOf(value) : ""));
相关推荐
学逆向的17 分钟前
C 堆区内存管理
c语言·开发语言·网络安全
huoyueyi32 分钟前
《融天AI-APP从0到1开发实录》
开发语言·lua
智能运维指南1 小时前
研制过程“两张皮“怎么破:研制一体化支撑平台的定位、能力边界与落地前提
java·前端·人工智能·嘉为蓝鲸
yz_aiks2 小时前
Spring AI 2.1 ChatMemory 已过时用什么替代:迁移到 Session Memory 实战(JDBC 存储与会话压缩)
java·spring boot·大模型·ai agent·spring ai
金銀銅鐵2 小时前
[Java] 用 GUI 展示 EnumMap 增删键值对时的内部变化
java·后端·ai编程
学长毕设2 小时前
基于SpringBoot的上门洗车服务系统设计与实现
java·spring boot·后端
jason成都2 小时前
RTKLIB-Java 多基线联合RTK:FIX率从0%到91.5%的三层根因修复
java·gnss·rtklib·rtklib_java
OpenAnolis小助手2 小时前
PHP 两个严重漏洞曝光,龙蜥社区 24 小时完成 3 版本修复
开发语言·操作系统·php·龙蜥社区
鱼宵2 小时前
Stream 终端操作一次讲透:collect、count、reduce 怎么选
java·stream·终端操作
白山编程大哥2 小时前
Java 后端如何优雅地把 List 集合返回给前端
java·前端·list