RedisTemplate进行对象序列化踩坑

RedisTemplate 默认使用 JdkSerializationRedisSerializer 对对象进行序列化
RedisTemplate 相关源码如下:

private @Nullable RedisSerializer<?> defaultSerializer;

@SuppressWarnings("rawtypes") private @Nullable RedisSerializer keySerializer = null;
@SuppressWarnings("rawtypes") private @Nullable RedisSerializer valueSerializer = null;
@SuppressWarnings("rawtypes") private @Nullable RedisSerializer hashKeySerializer = null;
@SuppressWarnings("rawtypes") private @Nullable RedisSerializer hashValueSerializer = null;

@Override
public void afterPropertiesSet() {

    super.afterPropertiesSet();

    boolean defaultUsed = false;

    if (defaultSerializer == null) {

        defaultSerializer = new JdkSerializationRedisSerializer(
            classLoader != null ? classLoader : this.getClass().getClassLoader());
    }

    if (enableDefaultSerializer) {

        if (keySerializer == null) {
            keySerializer = defaultSerializer;
            defaultUsed = true;
        }
        if (valueSerializer == null) {
            valueSerializer = defaultSerializer;
            defaultUsed = true;
        }
        if (hashKeySerializer == null) {
            hashKeySerializer = defaultSerializer;
            defaultUsed = true;
        }
        if (hashValueSerializer == null) {
            hashValueSerializer = defaultSerializer;
            defaultUsed = true;
        }
    }

    if (enableDefaultSerializer && defaultUsed) {
        Assert.notNull(defaultSerializer, "default serializer null and not all serializers initialized");
    }

    if (scriptExecutor == null) {
        this.scriptExecutor = new DefaultScriptExecutor<>(this);
    }

    initialized = true;
}


这里自定义 RedisTemplate,使用 GenericJackson2JsonRedisSerializer,代码如下:

@Configuration
public class RedisConfig {

    //向容器中添加 **GenericJackson2JsonRedisSerializer** 对象
    @Bean(name = "springSessionDefaultRedisSerializer")
    public GenericJackson2JsonRedisSerializer getGenericJackson2JsonRedisSerializer() {
        return new GenericJackson2JsonRedisSerializer();
    }

    //向容器中添加自定义的 **RedisTemplate**
    @Bean
    public RedisTemplate<String, Object> getRedisTemplate( RedisConnectionFactory connectionFactory) {
        //创建 **RedisTemplate **对象
        RedisTemplate<String, Object> redisTemplate = new RedisTemplate<>();
        //设置 **RedisTemplate ** 的 **ConnectionFactory**
        redisTemplate.setConnectionFactory(connectionFactory);
        //设置 **RedisTemplate ** 的默认序列化器 **defaultSerializer**
        redisTemplate.setDefaultSerializer(new GenericJackson2JsonRedisSerializer());

        //设置 **key**、**hashKey **的序列化器为 **StringRedisSerializer**
        StringRedisSerializer stringRedisSerializer = new StringRedisSerializer();
        redisTemplate.setKeySerializer(stringRedisSerializer);
        redisTemplate.setHashKeySerializer(stringRedisSerializer);

        return redisTemplate;
    }
}


所遇异常:

1. org.springframework.data.redis.serializer.SerializationException: Could not write JSON: (was java.lang.NullPointerException) (through reference chain: com.atguigu.bookcity.pojo.CartItem["xj"]); nested exception is com.fasterxml.jackson.databind.JsonMappingException: (was java.lang.NullPointerException) (through reference chain: com.atguigu.bookcity.pojo.CartItem["xj"])
2. org.springframework.data.redis.serializer.SerializationException: Could not write JSON: (was java.lang.NullPointerException) (through reference chain: com.atguigu.bookcity.pojo.OrderItem["xj"]); nested exception is com.fasterxml.jackson.databind.JsonMappingException: (was java.lang.NullPointerException) (through reference chain: com.atguigu.bookcity.pojo.OrderItem["xj"])


原因:我定义的两个实体类 CartItemOrderItem 中有 getXXX() 方法,但没有对应的属性,而 GenericJackson2JsonRedisSerializer 序列化会调用 getXXX() 方法为相应属性赋值,故报错
原始实体类定义如下:

package com.atguigu.bookcity.pojo;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.ToString;

import java.math.BigDecimal;

/**
 * @author ycjstart
 * @create 2022-11-16 16:15
 */
@Data
@ToString
@NoArgsConstructor
@AllArgsConstructor
public class CartItem {

    private Integer id;

    private Book book;

    private Integer buyCount;

    private Integer userBean;


    public Double getXj() {
        BigDecimal bookPrice = BigDecimal.valueOf(book.getPrice());
        return  (bookPrice.multiply(new BigDecimal(buyCount)).doubleValue());
    }

}

package com.atguigu.bookcity.pojo;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.ToString;

import java.math.BigDecimal;

/**
 * @author ycjstart
 * @create 2022-11-16 16:18
 */
@Data
@ToString
@NoArgsConstructor
@AllArgsConstructor
public class OrderItem {

    private Integer id;

    private Book book;

    private Integer buyCount;

    private Integer orderId;


    public OrderItem(Book book, Integer buyCount, Integer orderId) {
        this.book = book;
        this.buyCount = buyCount;
        this.orderId = orderId;
    }

    public Double getXj() {

        BigDecimal bookPrice = BigDecimal.valueOf(book.getPrice());
        return bookPrice.multiply(BigDecimal.valueOf(buyCount)).doubleValue();

    }

}


修改后实体类:

package com.atguigu.bookcity.pojo;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.ToString;

import java.math.BigDecimal;

/**
 * @author ycjstart
 * @create 2022-11-16 16:15
 */
@Data
@ToString
@NoArgsConstructor
@AllArgsConstructor
public class CartItem {

    private Integer id;

    private Book book;

    private Integer buyCount;

    private Integer userBean;


    public Double calculateXj() {
        BigDecimal bookPrice = BigDecimal.valueOf(book.getPrice());
        return  (bookPrice.multiply(new BigDecimal(buyCount)).doubleValue());
    }

}

package com.atguigu.bookcity.pojo;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.ToString;

import java.math.BigDecimal;

/**
 * @author ycjstart
 * @create 2022-11-16 16:18
 */
@Data
@ToString
@NoArgsConstructor
@AllArgsConstructor
public class OrderItem {

    private Integer id;

    private Book book;

    private Integer buyCount;

    private Integer orderId;


    public OrderItem(Book book, Integer buyCount, Integer orderId) {
        this.book = book;
        this.buyCount = buyCount;
        this.orderId = orderId;
    }

    public Double calculateXj() {

        BigDecimal bookPrice = BigDecimal.valueOf(book.getPrice());
        return bookPrice.multiply(BigDecimal.valueOf(buyCount)).doubleValue();

    }

}


方法名修改后,异常解决

posted @   MuYg  阅读(741)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通
点击右上角即可分享
微信分享提示