因爲項目使用的是fastjson,也沒法換成其餘的序列化框架,因此研究了一下他對泛型序列化和反序列化的支持能力,最終解決了這個問題。html
要達成的目標json
個人封裝方式屬於通用封裝,我要達到的目標是以下的使用方式:app
放入數據:框架
Map<String, OffheapDTO> mapxx = new HashMap<>(); mapxx.put("1",new OffheapDTO().create()); mapxx.put("2",new OffheapDTO().create()); mapxx.put("3",new OffheapDTO().create()); mapxx.put("4",new OffheapDTO().create()); mapxx.put("5",new OffheapDTO().create()); offheapCacheWrapper.putMap("maptest", mapxx);
獲取數據:less
Map<String, OffheapDTO> resultmap = offheapCacheWrapper.queryMap("cachemap")
OffheapDTO對象的定義方式以下:spa
class OffheapDTO implements Serializable, Comparable{ private String name; private String address; private String mark; private int order; //省略getset }
也就是我能夠隨意的把任何對象進行序列化操做,而後能夠隨意的把任何已經序列化的對象,反序列化回來。調試
初版代碼代碼,未中其意code
putMap方法代碼以下:
public <T> void putMap(String key, T value, long expireSeconds) {
try { EntityWrapper<T> entityWrapper = new EntityWrapper<>().create(key, value, expireSeconds); initMapContainer(OffheapCacheConst.MAP_CONTAINER_FOR_STRING).put(key, JSON.toJSONString(entityWrapper)); } catch (Exception ex) { logger.error(OffheapCacheConst.PACKAGE_CONTAINER + "putMapSingle with expires exception:", ex); throw ex; }
}
queryMap方法代碼以下:htm
public <T> T queryMap(String key) { try { Object result = initMapContainer(OffheapCacheConst.MAP_CONTAINER_FOR_STRING).get(key); if(result == null){ return null; } //反序列化出entityWrapper EntityWrapper entityWrapper = JSON.parseObject(result.toString()); return (T)entityWrapper.getEntity(); } catch (Exception ex) { logger.error(OffheapCacheConst.PACKAGE_CONTAINER + "queryMap exception:", ex); return null; }
}
結果當我反序列化的時候,調用resultmap.get("1")的時候,提示我沒法將jsonObject轉變成OffheapDTO. 調試進去發現,List對象裏面裝載的仍然是jsonObject數據。初次嘗試失敗。對象
第二版代碼,苦盡甘來
以後翻看了百度,查閱了大量資料,而後看到了關於TypeReference的代碼,以後將queryMap方法修改以下:
public <T> T queryMap(String key) { try { Object result = initMapContainer(OffheapCacheConst.MAP_CONTAINER_FOR_STRING).get(key); if(result == null){ return null; } //反序列化出entityWrapper EntityWrapper entityWrapper = JSON.parseObject(result.toString(),new TypeReference<EntityWrapper<T>>() {});
return (T)entityWrapper.getEntity(); } catch (Exception ex) { logger.error(OffheapCacheConst.PACKAGE_CONTAINER + "queryMap exception:", ex); return null; } }
注意代碼中黃色部分。
而後當我再次進行反序列化的時候,我發現resultMap.get(「1」)已經能夠拿到正常的OffheapDTO對象了。心中一喜,而後運行resultMap.get(「1」).getName(), 竟然又報錯,提示沒法將jsonObject轉變成OffheapDTO對象,發現原來存儲的字段,竟然都是jsonObject類型。此次就有點慌了。
第三版代碼,驀然回首
不過想一想fastjson這麼成熟,定然有前人的輪子,因此就繼續查閱資料,終於查到了setAutoTypeSupport這個屬性,沒想到一試,竟然解決了問題。
首先,程序啓動的時候,須要開啓這個屬性,至於這個屬性真正的意義,去翻閱fastjson文檔,我這裏就不贅述了:
//開啓fastjson autotype功能(不開啓,形成EntityWrapper<T>中的T沒法正常解析) ParserConfig.getGlobalInstance().setAutoTypeSupport(true);
而後,在序列化的時候,須要附帶上序列化的class名稱(黃色標記部分):
public <T> void putMap(String key, T value, long expireSeconds) { try { EntityWrapper<T> entityWrapper = new EntityWrapper<>().create(key, value, expireSeconds); initMapContainer(OffheapCacheConst.MAP_CONTAINER_FOR_STRING).put(key, JSON.toJSONString(entityWrapper, SerializerFeature.WriteClassName));
} catch (Exception ex) { logger.error(OffheapCacheConst.PACKAGE_CONTAINER + "putMapSingle with expires exception:", ex); throw ex; } }
最後,在反序列化的時候,利用TypeReference進行類型指定便可:
public <T> T queryMap(String key) { try { Object result = initMapContainer(OffheapCacheConst.MAP_CONTAINER_FOR_STRING).get(key); if(result == null){ return null; } //反序列化出entityWrapper EntityWrapper entityWrapper = JSON.parseObject(result.toString(),new TypeReference<EntityWrapper<T>>() {});
return (T)entityWrapper.getEntity(); } catch (Exception ex) { logger.error(OffheapCacheConst.PACKAGE_CONTAINER + "queryMap exception:", ex); return null; } }
這樣,不管你的類有多複雜,均可以搞定,好比像下面這樣的:
Map<String,List< OffheapDTO>> resultmap = offheapCacheWrapper.queryMap("maptest");
甚至這樣的:
List<Map<String,List<Set<OffheapDTO>>>> resultmap = offheapCacheWrapper.queryMap("maptest");
Enjoy!!