由于项目使用的是fastjson,也无法换成其他的序列化框架,所以研究了一下他对泛型序列化和反序列化的支持能力,最终解决了这个问题。

要达成的目标

我的封装方式属于通用封装,我要达到的目标是如下的使用方式:

放入数据:

 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);

获取数据:

 Map<String, OffheapDTO> resultmap = offheapCacheWrapper.queryMap("cachemap")

OffheapDTO对象的定义方式如下:

class OffheapDTO implements Serializable, Comparable{
private String name;
private String address;
private String mark;
private int order;
//省略getset
}

也就是我可以随意的把任何对象进行序列化操作,然后可以随意的把任何已经序列化的对象,反序列化回来。

第一版代码代码,未中其意

 
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方法代码如下:

    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!!

基于FastJson的通用泛型解决方案的更多相关文章

  1. 基于dapper的通用泛型分页

    1.定义一个用来装载适合所有类的分页结果类 public class PageDataView<T> { private int _TotalNum; public PageDataVie ...

  2. Fastjson解析多级泛型的几种方式—使用class文件来解析多级泛型

    Fastjson解析多级泛型 前言 现在网上大多数是使用TypeReference 方式来解析JSON数据,这里我提供另外一种方式来解析,使用类文件进行解析,两种方式我都会给出实际代码 实例 Type ...

  3. 基于.net的分布式系统限流组件 C# DataGridView绑定List对象时,利用BindingList来实现增删查改 .net中ThreadPool与Task的认识总结 C# 排序技术研究与对比 基于.net的通用内存缓存模型组件 Scala学习笔记:重要语法特性

    基于.net的分布式系统限流组件   在互联网应用中,流量洪峰是常有的事情.在应对流量洪峰时,通用的处理模式一般有排队.限流,这样可以非常直接有效的保护系统,防止系统被打爆.另外,通过限流技术手段,可 ...

  4. #研发解决方案介绍#基于StatsD+Graphite的智能监控解决方案

    郑昀 基于李丹和刘奎的文档 创建于2014/12/5 关键词:监控.dashboard.PHP.graphite.statsd.whisper.carbon.grafana.influxdb.Pyth ...

  5. 构建一个基本的前端自动化开发环境 —— 基于 Gulp 的前端集成解决方案(四)

    通过前面几节的准备工作,对于 npm / node / gulp 应该已经有了基本的认识,本节主要介绍如何构建一个基本的前端自动化开发环境. 下面将逐步构建一个可以自动编译 sass 文件.压缩 ja ...

  6. 常用 Gulp 插件汇总 —— 基于 Gulp 的前端集成解决方案(三)

    前两篇文章讨论了 Gulp 的安装部署及基本概念,借助于 Gulp 强大的 插件生态 可以完成很多常见的和不常见的任务.本文主要汇总常用的 Gulp 插件及其基本使用,需要读者对 Gulp 有一个基本 ...

  7. 在windows下安装gulp —— 基于 Gulp 的前端集成解决方案(一)

    相关连接导航 在windows下安装gulp —— 基于 Gulp 的前端集成解决方案(一) 执行 $Gulp 时发生了什么 —— 基于 Gulp 的前端集成解决方案(二) 常用 Gulp 插件汇总 ...

  8. 执行 $Gulp 时发生了什么 —— 基于 Gulp 的前端集成解决方案(二)

    前言 文章 在windows下安装gulp —— 基于 Gulp 的前端集成解决方案(一) 中,已经完成对 gulp 的安装,由于是window环境,文中特意提到了可以通过安装 gitbash 来代替 ...

  9. Java魔法堂:解读基于Type Erasure的泛型

    一.前言 还记得JDK1.4时遍历列表的辛酸吗?我可是记忆犹新啊,那时因项目需求我从C#转身到Java的怀抱,然后因JDK1.4少了泛型这样语法糖(还有自动装箱.拆箱),让我受尽苦头啊,不过也反映自己 ...

随机推荐

  1. 希尔排序(Python实现)

    目录 1.for版本--希尔排序 2. while版本--希尔排序 3. 测试用例 4. 算法时间复杂度分析 1.for版本--希尔排序 def shell_sort_for(a_list): ''' ...

  2. javaScript函数立即执行《1》

    javaScript函数立即执行<1> 函数立即执行,常见两种写法: >>> (function(){ })() >>> (function(){ }( ...

  3. CentOS 7 之 Systemd 入门教程:命令篇

    Systemd 是 Linux 系统工具,用来启动守护进程,已成为大多数发行版的标准配置 历史上,Linux 的启动一直采用init进程 下面的命令用来启动服务 [root@DaMoWang ~]# ...

  4. Android-Gradle(一)

    理解基本的Gradle 如果你想创建一个Android project基于gradle,那么你必须写一个构建脚本,这个文件通常称之为build.grade,你可能已经觉察到了,当我们查看这一脚本,gr ...

  5. js 取消事件冒泡

    html部分 <input type="button" id="btn1" value="按钮" /> <div id=& ...

  6. Qt::WindowFlags枚举类型解析

    在使用Qt设计的时候经常会看到QWidget控件的构造函数出现下面这样一句话: QWidget(QWidget *parent=0,Qt::WindowFlags f=0) QWidget *pare ...

  7. Docker Weave 介绍 or 工作原理

    Docker Weave Network Weave Network:属于第三方网络项目. Weave在Docker主机之间实现Overlay网络,使用业界标准VXLAN封装,基于UDP传输,也可以加 ...

  8. Oracle 12c 的RMAN备份

    备份 rman只备份cdb 只备份CDB数据库需要具有SYSDBA或SYSBACKUP权限用户连接到CDB的root环境下,执行backupdatabase root命令即可完成对CDB的备份,方法如 ...

  9. 关于decode("utf-8")出现编码错的提示

    data = data.decode("utf-8") 出现错误时候可以加上第二个参数  如下; data = data.decode("utf-8",&quo ...

  10. P3346 [ZJOI2015]诸神眷顾的幻想乡

    思路 注意到叶子节点(度数为1)只有20个,可以分别以这20个节点为根,把所有子串插入SAM中,统计最后的本质不同的子串个数 所以就是广义SAM了 然后注意要判断一下有无重复插入 代码 #includ ...