因为项目使用的是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!!