由于项目使用的是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基础(13)-面向对象

    类 类的定义和使用 # class Person: def __init__(self, name, age, gender): self.name = name self.age = age sel ...

  2. openshift 容器云从入门到崩溃之九《容器监控-报警》

    容器状态监控 主要是监控POD的状态包括重启.不健康等等这些k8s api 状态本身会报出来,在配合zabbix报警 导入zabbix模板关联上oc master主机 <?xml version ...

  3. Ch02 控制结构和函数 - 练习

    1. 一个数字如果为正数,则它的signum为1:如果是负数,则signum为-1:如果是0,则signum为0.编写一个函数来计算这个值. scala> def signum(x:Int):I ...

  4. 如果merge分支出现问题,使用git方式查看日志

    Administrator@IT-20161115IKEG MINGW32 ~$ cd e: Administrator@IT-20161115IKEG MINGW32 /e$ ls$RECYCLE. ...

  5. ASP.NET Core 之 Identity

    Claims:声明(证件单元)Identity:身份Principal:当事人Authentication :认证Authorization:授权 http://www.cnblogs.com/sav ...

  6. 前端学习历程--css①

    ---恢复内容开始--- 本文用自己的理解,总结网上或者自身经历的问题,加以汇总,方便查找: 一.浏览器默认样式 1.浏览器处理css&html a.css作用范围:盒子模式.浮动.定位.背景 ...

  7. C#串口通信遇到的坑

    C#串口通信中有一个DataReceived事件可以委托一个接收函数.此接收函数是运行在辅线程(secondary thread)上的.如果要在这个函数中修改主线程中的一些元素,比如UI界面上的变量的 ...

  8. Angular4 HTTP通讯

  9. 时间序列预测——Tensorflow.Keras.LSTM

    1.测试数据下载 https://datamarket.com/data/set/22w6/portland-oregon-average-monthly-bus-ridership-100-janu ...

  10. python核心技术

    基本语法 Python的设计目标之一是让代码具备高度的可阅读性.它设计时尽量使用其它语言经常使用的标点符号和英文单字,让代码看起来整洁美观.它不像其他的静态语言如C.Pascal那样需要重复书写声明语 ...