redisTemplate序列化的坑

前置代码:

@Component
public class RedisUtil {
    @Autowired
    private RedisTemplate redisTemplate;

    public void set(Object key, Object value) {
        redisTemplate.opsForValue().set(key, value);
    }

    public void incr(Object key) {
        redisTemplate.opsForValue().increment(key);
    }
}

坑1:默认情况下, 采用JdkSerializationRedisSerializer作为序列化器,要实现自增只能直接调用自增,不能先set再调用自增,最大的坑是如果set进去的是java对象,对象成员属性有增加或者减少的时候,会导致get会报错,这个就不在这里演示了,如下

 

坑2:为了解决ERR value is not an integer or out of range这个报错, 需要设置一个序列化器:

@Component
public class RedisUtil {
    @Autowired
    private RedisTemplate redisTemplate;

    @PostConstruct
    public void setRedisSerializer() {
        //key采用string序列化
        StringRedisSerializer keySerializer = new StringRedisSerializer();
        redisTemplate.setKeySerializer(keySerializer);
        redisTemplate.setHashKeySerializer(keySerializer);
        //值采用GenericJackson2JsonRedisSerializer
        GenericJackson2JsonRedisSerializer genericJackson2JsonRedisSerializer = new GenericJackson2JsonRedisSerializer();
        redisTemplate.setValueSerializer(genericJackson2JsonRedisSerializer);
        redisTemplate.setHashValueSerializer(genericJackson2JsonRedisSerializer);
    }

    public void set(Object key, Object value) {
        redisTemplate.opsForValue().set(key, value);
    }

    public Object get(Object key) {
        return redisTemplate.opsForValue().get(key);
    }

    public void incr(Object key) {
        redisTemplate.opsForValue().increment(key);
    }
}

但是会有另外一个问题:当set进去的是一个java对象并且里面含有LocalDateTime类型的时候,读取的时候会报错:

public class User implements Serializable {
    private int age;
    private String name;
    private LocalDateTime birthDay;

    public LocalDateTime getBirthDay() {
        return birthDay;
    }

    public void setBirthDay(LocalDateTime birthDay) {
        this.birthDay = birthDay;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}

 为了解决这个时间问题,继续换序列化器:

@Component
public class RedisUtil {
    @Autowired
    private RedisTemplate redisTemplate;

    @PostConstruct
    public void setRedisSerializer() {
        //key采用string序列化
        StringRedisSerializer keySerializer = new StringRedisSerializer();
        redisTemplate.setKeySerializer(keySerializer);
        redisTemplate.setHashKeySerializer(keySerializer);
        //值采用GenericJackson2JsonRedisSerializer
        GenericFastJsonRedisSerializer genericFastJsonRedisSerializer = new GenericFastJsonRedisSerializer();
        redisTemplate.setValueSerializer(genericFastJsonRedisSerializer);
        redisTemplate.setHashValueSerializer(genericFastJsonRedisSerializer);
    }

    public void set(Object key, Object value) {
        redisTemplate.opsForValue().set(key, value);
    }

    public Object get(Object key) {
        return redisTemplate.opsForValue().get(key);
    }

    public void incr(Object key) {
        redisTemplate.opsForValue().increment(key);
    }
}

单元测试通过:

 然后回测前面的坑1的两种情况,都能顺利通过,这里就不截图了,完美解决遇到的坑

总结:redisTemplate序列化的时候推荐使用GenericFastJsonRedisSerializer作为序列化器,这个是fastjson包里面带的,需要引入fastjson依赖:

        <dependency>
            <groupId>com.alibaba.</groupId>
            <artifactId>fastjson</artifactId>
            <version>1.2.70</version>
        </dependency>

 ps:如果项目中有用redisTemplate通过lua脚本实现分布式锁的话,GenericFastJsonRedisSerializer也有坑,推荐使用FastJsonRedisSerializer,完美解决所有问题,可以看看另一篇博客:

使用redisTemplate通过lua脚本实现分布式锁的坑_qq_17805707的博客-CSDN博客

猜你喜欢

转载自blog.csdn.net/qq_17805707/article/details/132047002