前置代码:
@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,完美解决所有问题,可以看看另一篇博客: