美文网首页编程学习笔记
SpringBoot+redis 使用jackson2JsonR

SpringBoot+redis 使用jackson2JsonR

作者: 烛火的咆哮 | 来源:发表于2019-04-19 12:43 被阅读0次

    错误提示

    org.springframework.data.redis.serializer.SerializationException: Could not read JSON: Cannot construct instance of `com.example.learn_1.entity.LearnUser` (no Creators, like default construct, exist): cannot deserialize from Object value (no delegate- or property-based Creator)
     at [Source: (byte[])"["com.example.learn_1.entity.LearnUser",{"userId":null,"userName":"唢呐","userAge":988,"remark":null}]"; line: 1, column: 42]; nested exception is com.fasterxml.jackson.databind.exc.InvalidDefinitionException: Cannot construct instance of `com.example.learn_1.entity.LearnUser` (no Creators, like default construct, exist): cannot deserialize from Object value (no delegate- or property-based Creator)
    

    代码

    RedisConfig
        @Bean("userRedistemplate")
        public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) {
            RedisTemplate<String, Object> template = new RedisTemplate<String, Object>();
            // 将刚才的redis连接工厂设置到模板类中
            template.setConnectionFactory(redisConnectionFactory);
            // 设置key的序列化器
            template.setKeySerializer(new StringRedisSerializer());
            // 设置value的序列化器
            //使用Jackson 2,将对象序列化为JSON
            Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class);
            //json转对象类,不设置默认的会将json转成hashmap
            ObjectMapper om = new ObjectMapper();
            om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
            om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
            jackson2JsonRedisSerializer.setObjectMapper(om);
            template.setValueSerializer(jackson2JsonRedisSerializer);
    
            return template;
        }
    
    entity
    @Data
    @Builder
    @Accessors(chain = true)
    public class LearnUser //extends BaseEntity
    {
        private static final long serialVersionUID = 1L;
    
        @TableId(value = "user_id", type = IdType.AUTO)
        private Integer userId;
    
        private String userName;
    
        private Integer userAge;
    
        private String remark;
    
    
    }
    
    test
        @Test
        public void testRedisTemplate(){
            // 以注解的形式把 bean 注入Spring 并获取 Spring 的上下文环境
            AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(RedisConfig.class);
            // 获取自己配置的 bean 实例
            RedisTemplate template = ctx.getBean(RedisTemplate.class);
            LearnUser user =  LearnUser.builder().userAge(988).userName("唢呐").build();
            template.opsForValue().set("key1", user);
            System.out.println(template.opsForValue().get("key1"));
        }
    

    解决

    1. 在entity中添加注解@AllArgsConstructor(access = AccessLevel.PRIVATE)
    2. 新建一个无参构造方法
        LearnUser(){
    
        }
    
    • 根据错误提示(no Creators, like default construct, exist)分析得无法创建实例
    • 报错行
    System.out.println(template.opsForValue().get("key1"));
    
    • 即在使用jackson2JsonRedisSerializer反序列化创建LearnUser对象时,发现LearnUser类中没有合适的构造方法,确定问题在LearnUser类中
    • 贴上链接https://www.jianshu.com/p/0d8fc3df3647?from=timeline&isappinstalled=0
    • 原因在于使用lombok插件,添加@Builder后,为LearnUser创建了一个全参的构造方法,而jackson2JsonRedisSerializer无法调用这个构造方法.
    • 添加注解后,@Builder为我们创建的构造方法会被修饰为Private,防止了@Builder注解对其他类的影响

    总结

    1. 关于@Builder为什么使用建造者模式,建议阅读Effective Java一书
    2. 只是一个小问题,虽然报错信息交杂,只要认真阅读,即可找到出路
    3. 学会利用idea的反编译工具
    4. 当没有定义构造方法时,java会自动创建一个无参的构造方法,当手动书写构造方法时,会使用手动书写的构造方法

    相关文章

      网友评论

        本文标题:SpringBoot+redis 使用jackson2JsonR

        本文链接:https://www.haomeiwen.com/subject/oadqgqtx.html