Redis存取List
实体类必须序列化,对于redis这种nosql数据库,实例化很重要,很多文章也都介绍了必须实例化,在配置redisTemplate时也会配置序列化规则:
<bean id="redisTemplate" class="org.springframework.data.redis.core.RedisTemplate">
<property name="connectionFactory" ref="jedisConnectionFactory" />
<property name="KeySerializer">
<bean
class="org.springframework.data.redis.serializer.StringRedisSerializer"></bean>
</property>
<property name="ValueSerializer">
<bean
class="org.springframework.data.redis.serializer.JdkSerializationRedisSerializer"></bean>
</property>
<property name="HashKeySerializer">
<bean
class="org.springframework.data.redis.serializer.StringRedisSerializer"></bean>
</property>
<property name="HashValueSerializer">
<bean
class="org.springframework.data.redis.serializer.JdkSerializationRedisSerializer"></bean>
</property>
</bean>
redis存取List api
//存入List<T>,需要实现序列化
public <T> void putCache(JedisCluster jedisCluster,String key ,List<T> list,Integer liveSeconds){
log.info("===========putCache===========key:"+key);
try {
if (null==liveSeconds ) {
jedisCluster.set(SerializationUtils.serialize(cacheConfig.getPreFixKey(key).getBytes()) ,SerializationUtils.serialize(list));
} else {
jedisCluster.setex(SerializationUtils.serialize(cacheConfig.getPreFixKey(key).getBytes()), liveSeconds, SerializationUtils.serialize(list));
}
} catch (Exception e) {
log.error("Set key error : "+e);
}
}
//取List<T>需要实现反序列化
public <T> List<T> getCache(JedisCluster jedisCluster,String key){
log.info("===========getCache===========key:"+key);
byte[] in = jedisCluster.get(SerializationUtils.serialize(cacheConfig.getPreFixKey(key).getBytes()));
if (null == in) {
return null;
}else{
List<T> list = (List<T>) SerializationUtils.deserialize(in);
return list;
}
}
//命名key的规则
public String getPreFixKey(String key){
return String.format("%s:%s",namespace,key);
}
SerializationUtils类
不管是存入还是取出,都是通过字节流,这也是序列化的原因。
public abstract class SerializationUtils {
/**
* Serialize the given object to a byte array.
* @param object the object to serialize
* @return an array of bytes representing the object in a portable fashion
*/
@Nullable
public static byte[] serialize(@Nullable Object object) {
if (object == null) {
return null;
}
ByteArrayOutputStream baos = new ByteArrayOutputStream(1024);
try {
ObjectOutputStream oos = new ObjectOutputStream(baos);
oos.writeObject(object);
oos.flush();
}
catch (IOException ex) {
throw new IllegalArgumentException("Failed to serialize object of type: " + object.getClass(), ex);
}
return baos.toByteArray();
}
/**
* Deserialize the byte array into an object.
* @param bytes a serialized object
* @return the result of deserializing the bytes
*/
@Nullable
public static Object deserialize(@Nullable byte[] bytes) {
if (bytes == null) {
return null;
}
try {
ObjectInputStream ois = new ObjectInputStream(new ByteArrayInputStream(bytes));
return ois.readObject();
}
catch (IOException ex) {
throw new IllegalArgumentException("Failed to deserialize object", ex);
}
catch (ClassNotFoundException ex) {
throw new IllegalStateException("Failed to deserialize object type", ex);
}
}
}
bug:Failed to serialize object of type: class com.google.common.collect.Lists$Revers
产生这个bug的原因是因为Lists.Revers没有实现序列化,所以存入redis的时候会报这个错误,当时遇到这个bug也查了好长时间,最后看这个Lists.Revers源码才发现这个问题。包括Lists.partition(),List.subList()等都没有实现序列化。
解决
将Lists.Revers、Lists.partition(),List.subList()等重新装入到已经实现序列化的list中去,问题解决
//Lists.Revers转list
List<User> list = new LinkedList<User>();
List<User> resutlListReverse = Lists.reverse(resutlList);
list.addAll(resutlListReverse);
//List.subList转list
List<User> subList = List.subList(0,10);
list.addAll(subList);