Redis存取List
实体类必须序列化,对于redis这种nosql数据库,实例化很重要,很多文章也都介绍了必须实例化,在配置redisTemplate时也会配置序列化规则:
<bean id="redisTemplate" class="org.springframework.data.redis.core.RedisTemplate"><property name="connectionFactory" ref="jedisConnectionFactory" /><property name="KeySerializer"><beanclass="org.springframework.data.redis.serializer.StringRedisSerializer"></bean></property><property name="ValueSerializer"><beanclass="org.springframework.data.redis.serializer.JdkSerializationRedisSerializer"></bean></property><property name="HashKeySerializer"><beanclass="org.springframework.data.redis.serializer.StringRedisSerializer"></bean></property><property name="HashValueSerializer"><beanclass="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*/@Nullablepublic 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*/@Nullablepublic 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 mon.collect.Lists$Revers
产生这个bug的原因是因为Lists.Revers没有实现序列化,所以存入redis的时候会报这个错误,当时遇到这个bug也查了好长时间,最后看这个Lists.Revers源码才发现这个问题。包括Lists.partition(),List.subList()等都没有实现序列化。
解决
将Lists.Revers、Lists.partition(),List.subList()等重新装入到已经实现序列化的list中去,问题解决
//Lists.Revers转listList<User> list = new LinkedList<User>(); List<User> resutlListReverse = Lists.reverse(resutlList);list.addAll(resutlListReverse);//List.subList转listList<User> subList = List.subList(0,10);list.addAll(subList);