Redis序列化儲存Java集合List等自定義型別

小雷FansUnion發表於2015-11-17

在“Redis學習總結和相關資料”http://blog.csdn.net/fansunion/article/details/49278209
這篇文章中,對Redis做了總體的介紹,演示了Jedis和SpringDataRedis訪問Redis的相關例子。
對於基本的CRUD差不多夠了。

隨著專案中使用場景的增多,出現了儲存Java集合List的情況。
這個時候,一般的程式碼很可能會報錯,比如“無法序列化”,“序列化失敗”之類的~

經過幾個小時的實踐探索,參考了在秒針工作的程式碼以及最近的程式碼,有2種可行方法。

需要說明的是,專案中用的是SpringDataRedis,但是Jedis程式碼的思路也是一樣的。


專案中的Redis配置
<bean id="businessRedisTemplate" class="org.springframework.data.redis.core.StringRedisTemplate">
		<property name="connectionFactory" ref="businessConnectionFactory" />
		<!--如果不配置Serializer,那麼儲存的時候智慧使用String,如果用User型別儲存,那麼會提示錯誤User can't cast 
			to String!!! -->
		<property name="keySerializer">
			<bean
				class="org.springframework.data.redis.serializer.StringRedisSerializer" />
		</property>
		<property name="valueSerializer">
			<bean
				class="org.springframework.data.redis.serializer.JdkSerializationRedisSerializer" />
		</property>
	</bean>

直接儲存java.util.List會提示“無法序列化”,“JdkSerializationRedisSerializer序列化失敗”類似的錯誤,
簡單的把java.util.List的元素實現Serialiable介面,是不行的。
也考慮了下,是不是和List元素的serialVersionUID有關係,最初用的是預設值1,改成系統生成的,也還是不行.
private static final long serialVersionUID = -2162380932844568332L;
方法1:把List轉換成JSON,儲存到Redis,取出來的時候,再把JSON轉換成List。
這種方法也很不錯,但是,當時咋就沒有想到呢。
序列化儲存
 
List list = new ArrayList();
  String json=JSONObject.toJSONString(list);
  logger.info("save json="+json);
  defaultCache.add(key, json, CATCHE_TIME);

 
反序列化
     
  Object jsonInRedis = defaultCache.getValue(key);
		List<MatchContent> list = null;
		Object listInRedis = null;
		if(jsonInRedis != null){
			logger.info("get json="+jsonInRedis);
			listInRedis= JSONObject.parseArray(jsonInRedis.toString(), MatchContent.class);
		}
		if (listInRedis instanceof List) {
			list = (List) listInRedis;
			logger.debug("Find fund4Project in redis~ size=" + list.size());
		}

需要特別說明的是, JSONObject.parseArray可以把json格式的字串,轉換成Java的List。
這個方法之前用的少,一直不熟悉,第2個引數是List元素的class。
  自己寫的1個Demo。
public static void main(String[] args) {
		List list = new ArrayList();
		list.add(new User());
		String json=JSONObject.toJSONString(list);
		System.out.println(json);
		List newList=JSONObject.parseArray(json, User.class);
		System.out.println(newList.size());
		
	}

方法2:把List轉換成二進位制陣列byte[],儲存到Redis,取出來的時候,再把byte[]轉成List。
序列化list->byte[]
import hprose.io.HproseFormatter;
java.io.ByteArrayOutputStream baos=HproseFormatter.serialize(list);
			byte[] bytes=baos.toByteArray();

二進位制反序列化byte[]->list
 listInRedis = HproseFormatter.unserialize((byte[] )bytesInRedis);
 
 專案中用的是原始碼,從秒針程式碼中copy出來的庫。
 
 上述2種方法,使用JSON序列化儲存,感覺更簡單一些。
 但是據說HproseFormatter這個庫,很牛逼,按照官網的說法。

 Hprose(High Performance Remote Object Service Engine)
是一款先進的輕量級、跨語言、跨平臺、無侵入式、高效能動態遠端物件呼叫引擎庫。它不僅簡單易用,而且功能強大。
你無需專門學習,只需看上幾眼,就能用它輕鬆構建分散式應用系統。

 網上找到了hprose的資料,不出意外的話,可以用下面這個的。
 hprose/hprose-java
 https://github.com/hprose/hprose-java/tree/master/src
  
  Map等其它型別的儲存,和List類似~
  
  把Redis序列化這個問題解決了,感覺方法很簡單。
 還是那句經典的話“難題不會,會題不難”。
 等把問題解決了,再難的問題,已經變得簡單了。沒解決的時候,急死你。
 夥計,加油~

相關文章