redis序列化自定义类,踩坑之路(感觉能踩的都踩了。。。)

1 起因

(只是一个菜鸡)在某个项目时,需要用redis缓存一些数据,然后就发现从java存到redis的信息,不论是key,还是value都会有一些奇怪的符号,如下图
key
会多出一些\xac\xed\x00\x05t\x00,而且这样是无法在redis-cli get到值的,比如 get \xac\xed\x00\x05t\x00\x1fpromo_token_1_userId_6_itemId_6 这样得不到值,是nil

value值同样
value
起初我以为这样的话,java也会get不到值,然后我就开始配置redisConfig了。。。

2 redisConfig自定义配置

sp给我们提供了RedisTemplate,StringRedisTemplate
redis的基本数据类型有五种,分别String,LIst,Set,Hash,Zset(特殊类型有三种),其中String用得最多,所以会有一个StringRedisTemplate,其实StringRedisTemplate也是继承于RedisTemplate<String,String>,
StringRedisTemplated的序列化方是string,而RedisTemplate默认的序列化方式为JDK的序列化策略,所以自己配置他的序列化策略,可以用ackson2JsonRedisSerializer,GenericToStringSerializer,StringRe
disSerializer。。。

public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory factory) {
        RedisTemplate<String,Object> redisTemplate = new RedisTemplate();
        //配置连接池工厂
        redisTemplate.setConnectionFactory(factory);
        //使用Jackson2JsonRedisSerializer的方式来序列化和反序列化redis的key和value(默认使用JDK的序列化的方式)
        Jackson2JsonRedisSerializer<Object> jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class);
        ObjectMapper om=new ObjectMapper();
        // 指定要序列化的域,field,get和set,以及修饰符范围,ANY是都有包括private和public
        om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
        // 指定序列化输入的类型,类必须是非final修饰的,final修饰的类,比如String,Integer抛出异常
        om.activateDefaultTyping(LaissezFaireSubTypeValidator.instance,ObjectMapper.DefaultTyping.NON_FINAL);
        jackson2JsonRedisSerializer.setObjectMapper(om);
        RedisSerializer stringSerializer = new StringRedisSerializer();
        //使用StringRedisSerializer的方式来序列化redis的key值
        redisTemplate.setKeySerializer(stringSerializer);
        redisTemplate.setHashKeySerializer(stringSerializer);
        //使用jackson2JsonRedisSerializer来序列化和反序列话redis的value值
        redisTemplate.setValueSerializer(jackson2JsonRedisSerializer);
        redisTemplate.setHashValueSerializer(jackson2JsonRedisSerializer);
        redisTemplate.afterPropertiesSet();
        return redisTemplate;
    }

这个这个设置很重要,我之前就是没设置这个,导致报异常(这个也是坑)
这个设置的意思就是他不会把String,Integer等类型的数据按照我们的序列化方式

om.activateDefaultTyping(LaissezFaireSubTypeValidator.instance,ObjectMapper.DefaultTyping.NON_FINAL);

3 继续踩坑

本来以为可以愉快的玩耍了,没想到又来了。。。

@Data
@AllArgsConstructor
@NoArgsConstructor
public class ItemModel implements Serializable {

    private static final long serialVersionUID=1L;

    //商品id
    private Integer id;

    //商品名称
    private String title;

    //商品价格
    private BigDecimal price;

    //商品库存
    private Integer stock;

    //商品描述
    private String description;

    //商品销量
    private Integer sales;

    //商品描述图片的url
    private String imgUrl;

    //活动商品信息
    private PromoModel promoModel;
}
@Data
@AllArgsConstructor
@NoArgsConstructor
public class PromoModel implements Serializable {

    private static final long serialVersionUID=1L;

    //秒杀活动状态 1.还未开始 2.在进行中 3.已结束
    private Integer status;

    private Integer id;

    //秒杀活动名称
    private String promoName;

    //秒杀活动开始的时间
    DateTime startDate;

    DateTime endTime;

    //秒杀活动适用商品
    Integer itemId;

    //秒杀活动对应的价格
    BigDecimal promoItemPrice;
}

当我要序列化ItemModel(当promoModel为空时序列化正常)这个类的时候,发现又乱码了,而且是很长很长,完全不知道存的是什么,就像这样
乱码

Resolved [org.springframework.data.redis.serializer.SerializationException: Could not read JSON: Cannot construct instance of `org.joda.time.chrono.ISOChronology` (no Creators, like default construct, exist): cannot deserialize from Object value (no delegate- or property-based Creator)

根据他的报错提示,是反序列化错误,然后是缺少构造,但是我的POJO无参有参都是存在的,然后我也看到大神们说是时间问题,然后我就把Joda time的时区变为了和数据库一样的,但是没啥用啊(是我菜。。。),然后我就怀疑是不是序列化的时候就出现问题,导致反序列化就一定会有问题。

4 光明

解决的办法就是昨晚看到了一篇博客,在比较后面了。。。那个大神说,JDk的序列化方式只是在redis里存着是那样,但是可以正常存取,所以我就把RedisConfig都注掉了。。。然后就发现序列化和反序列化都正常了!!!
唉,真的是我菜,这个问题困扰了我一天半,昨天晚上才解决。。。还要努力学习!!!持续进步

  • 4
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Spring Boot提供了与Redis的集成支持,可以通过配置和使用Spring Data Redis来实现。下面是整合Redis并实现自定义序列化的步骤: 1. 添加依赖:在`pom.xml`文件中添加Spring Data Redis的依赖: ```xml <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-redis</artifactId> </dependency> ``` 2. 配置Redis连接信息:在`application.properties`或`application.yml`文件中配置Redis的连接信息,例如: ```properties spring.redis.host=127.0.0.1 spring.redis.port=6379 ``` 3. 创建Redis配置:创建一个配置,用于配置Redis连接工厂和RedisTemplate等相关配置。可以参考以下示例: ```java @Configuration @EnableCaching public class RedisConfig extends CachingConfigurerSupport { @Bean public RedisConnectionFactory redisConnectionFactory() { RedisStandaloneConfiguration config = new RedisStandaloneConfiguration(); config.setHostName("127.0.0.1"); config.setPort(6379); return new LettuceConnectionFactory(config); } @Bean public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) { RedisTemplate<String, Object> template = new RedisTemplate<>(); template.setConnectionFactory(redisConnectionFactory); template.setDefaultSerializer(new GenericJackson2JsonRedisSerializer()); return template; } } ``` 在上述示例中,我们使用了Lettuce作为Redis的连接工厂,并设置了默认的序列化器为`GenericJackson2JsonRedisSerializer`,这样可以将对象以JSON格式进行序列化和反序列化。 4. 实现自定义序列化:如果需要自定义序列化方式,可以创建一个实现了`RedisSerializer`接口的自定义序列化器。例如,我们可以创建一个自定义的JSON序列化器: ```java public class CustomJsonRedisSerializer<T> implements RedisSerializer<T> { private final ObjectMapper objectMapper; public CustomJsonRedisSerializer() { this.objectMapper = new ObjectMapper(); this.objectMapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY); this.objectMapper.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL); } @Override public byte[] serialize(T t) throws SerializationException { if (t == null) { return new byte; } try { return objectMapper.writeValueAsBytes(t); } catch (JsonProcessingException e) { throw new SerializationException("Error serializing object to JSON: " + e.getMessage(), e); } } @Override public T deserialize(byte[] bytes) throws SerializationException { if (bytes == null || bytes.length == 0) { return null; } try { return objectMapper.readValue(bytes, new TypeReference<T>() {}); } catch (IOException e) { throw new SerializationException("Error deserializing object from JSON: " + e.getMessage(), e); } } } ``` 在上述示例中,我们使用了Jackson库来进行JSON的序列化和反序列化。 5. 使用自定义序列化器:在Redis配置中,将自定义序列化器设置为RedisTemplate的序列化器: ```java @Configuration @EnableCaching public class RedisConfig extends CachingConfigurerSupport { // ... @Bean public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) { RedisTemplate<String, Object> template = new RedisTemplate<>(); template.setConnectionFactory(redisConnectionFactory); template.setDefaultSerializer(new CustomJsonRedisSerializer<>()); return template; } } ``` 通过以上步骤,你就可以实现Spring Boot与Redis的整合,并使用自定义序列化器来对对象进行序列化和反序列化了。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值