Java学习者论坛

 找回密码
 立即注册

QQ登录

只需一步,快速开始

手机号码,快捷登录

恭喜Java学习者论坛(https://www.javaxxz.com)已经为数万Java学习者服务超过8年了!积累会员资料超过10000G+
成为本站VIP会员,下载本站10000G+会员资源,购买链接:点击进入购买VIP会员
JAVA高级面试进阶视频教程Java架构师系统进阶VIP课程

分布式高可用全栈开发微服务教程

Go语言视频零基础入门到精通

Java架构师3期(课件+源码)

Java开发全终端实战租房项目视频教程

SpringBoot2.X入门到高级使用教程

大数据培训第六期全套视频教程

深度学习(CNN RNN GAN)算法原理

Java亿级流量电商系统视频教程

互联网架构师视频教程

年薪50万Spark2.0从入门到精通

年薪50万!人工智能学习路线教程

年薪50万!大数据从入门到精通学习路线年薪50万!机器学习入门到精通视频教程
仿小米商城类app和小程序视频教程深度学习数据分析基础到实战最新黑马javaEE2.1就业课程从 0到JVM实战高手教程 MySQL入门到精通教程
查看: 276|回复: 0

[默认分类] 基于FastJson的通用泛型解决方案

[复制链接]
  • TA的每日心情
    开心
    2021-12-13 21:45
  • 签到天数: 15 天

    [LV.4]偶尔看看III

    发表于 2020-8-3 15:34:35 | 显示全部楼层 |阅读模式
    由于项目使用的是fastjson,也无法换成其他的序列化框架,所以研究了一下他对泛型序列化和反序列化的支持能力,最终解决了这个问题。
    要达成的目标
    我的封装方式属于通用封装,我要达到的目标是如下的使用方式:
    放入数据:
    1. Map<String, OffheapDTO> mapxx = new HashMap<>();
    2.         mapxx.put("1",new OffheapDTO().create());
    3.         mapxx.put("2",new OffheapDTO().create());
    4.         mapxx.put("3",new OffheapDTO().create());
    5.         mapxx.put("4",new OffheapDTO().create());
    6.         mapxx.put("5",new OffheapDTO().create());
    7.         offheapCacheWrapper.putMap("maptest", mapxx);
    复制代码


    获取数据:
    1. Map<String, OffheapDTO> resultmap = offheapCacheWrapper.queryMap("cachemap")
    复制代码

    OffheapDTO对象的定义方式如下:
    1. class OffheapDTO implements Serializable, Comparable{
    2.     private String name;
    3.     private String address;
    4.     private String mark;
    5.     private int order;
    6.    //省略getset
    7. }
    复制代码


    也就是我可以随意的把任何对象进行序列化操作,然后可以随意的把任何已经序列化的对象,反序列化回来。
    第一版代码代码,未中其意
    复制代码
    1. putMap方法代码如下:
    复制代码
    1.     public <T> void putMap(String key, T value, long expireSeconds) {
    复制代码
    1.         try {
    2.             EntityWrapper<T> entityWrapper = new EntityWrapper<>().create(key, value, expireSeconds);
    3.             initMapContainer(OffheapCacheConst.MAP_CONTAINER_FOR_STRING).put(key, JSON.toJSONString(entityWrapper));
    4.         } catch (Exception ex) {
    5.             logger.error(OffheapCacheConst.PACKAGE_CONTAINER + "putMapSingle with expires exception:", ex);
    6.             throw ex;
    7.         }
    复制代码
    1.     }
    复制代码


    queryMap方法代码如下:
    1.     public <T> T queryMap(String key) {
    2.         try {
    3.             Object result = initMapContainer(OffheapCacheConst.MAP_CONTAINER_FOR_STRING).get(key);
    4.             if(result == null){
    5.                 return null;
    6.             }
    7.             //反序列化出entityWrapper
    8.             EntityWrapper entityWrapper = JSON.parseObject(result.toString());
    9.             return (T)entityWrapper.getEntity();
    10.         } catch (Exception ex) {
    11.             logger.error(OffheapCacheConst.PACKAGE_CONTAINER + "queryMap exception:", ex);
    12.             return null;
    13.         }
    复制代码
    1.     }
    复制代码


    结果当我反序列化的时候,调用resultmap.get("1")的时候,提示我无法将jsonObject转变成OffheapDTO. 调试进去发现,List对象里面装载的仍然是jsonObject数据。初次尝试失败。
    第二版代码,苦尽甘来
    之后翻看了百度,查阅了大量资料,然后看到了关于TypeReference的代码,之后将queryMap方法修改如下:
    1.     public <T> T queryMap(String key) {
    2.         try {
    3.             Object result = initMapContainer(OffheapCacheConst.MAP_CONTAINER_FOR_STRING).get(key);
    4.             if(result == null){
    5.                 return null;
    6.             }
    7.             //反序列化出entityWrapper
    8.             EntityWrapper entityWrapper = JSON.parseObject(result.toString(),new TypeReference<EntityWrapper<T>>() {});
    复制代码
    1.             return (T)entityWrapper.getEntity();
    2.         } catch (Exception ex) {
    3.             logger.error(OffheapCacheConst.PACKAGE_CONTAINER + "queryMap exception:", ex);
    4.             return null;
    5.         }
    6.     }
    复制代码

    注意代码中黄色部分。
    然后当我再次进行反序列化的时候,我发现resultMap.get(“1”)已经可以拿到正常的OffheapDTO对象了。心中一喜,然后运行resultMap.get(“1”).getName(), 居然又报错,提示无法将jsonObject转变成OffheapDTO对象,发现原来存储的字段,居然都是jsonObject类型。这次就有点慌了。
    第三版代码,蓦然回首
    不过想想fastjson这么成熟,定然有前人的轮子,所以就继续查阅资料,终于查到了setAutoTypeSupport这个属性,没想到一试,居然解决了问题。
    首先,程序启动的时候,需要开启这个属性,至于这个属性真正的意义,去翻阅fastjson文档,我这里就不赘述了:
    1.       //开启fastjson autotype功能(不开启,造成EntityWrapper<T>中的T无法正常解析)
    2.         ParserConfig.getGlobalInstance().setAutoTypeSupport(true);
    复制代码

    然后,在序列化的时候,需要附带上序列化的class名称(黄色标记部分):
    1.     public <T> void putMap(String key, T value, long expireSeconds) {
    2.         try {
    3.             EntityWrapper<T> entityWrapper = new EntityWrapper<>().create(key, value, expireSeconds);
    4.             initMapContainer(OffheapCacheConst.MAP_CONTAINER_FOR_STRING).put(key, JSON.toJSONString(entityWrapper, SerializerFeature.WriteClassName));
    复制代码
    1.         } catch (Exception ex) {
    2.             logger.error(OffheapCacheConst.PACKAGE_CONTAINER + "putMapSingle with expires exception:", ex);
    3.             throw ex;
    4.         }
    5.     }
    复制代码

    最后,在反序列化的时候,利用TypeReference进行类型指定即可:
    1.     public <T> T queryMap(String key) {
    2.         try {
    3.             Object result = initMapContainer(OffheapCacheConst.MAP_CONTAINER_FOR_STRING).get(key);
    4.             if(result == null){
    5.                 return null;
    6.             }
    7.             //反序列化出entityWrapper
    8.             EntityWrapper entityWrapper = JSON.parseObject(result.toString(),new TypeReference<EntityWrapper<T>>() {});
    复制代码
    1.             return (T)entityWrapper.getEntity();
    2.         } catch (Exception ex) {
    3.             logger.error(OffheapCacheConst.PACKAGE_CONTAINER + "queryMap exception:", ex);
    4.             return null;
    5.         }
    6.     }
    复制代码

    这样,无论你的类有多复杂,都可以搞定,比如像下面这样的:
    1. Map<String,List< OffheapDTO>> resultmap = offheapCacheWrapper.queryMap("maptest");
    复制代码

    甚至这样的:
    1. List<Map<String,List<Set<OffheapDTO>>>> resultmap = offheapCacheWrapper.queryMap("maptest");
    复制代码

    Enjoy!!
    回复

    使用道具 举报

    您需要登录后才可以回帖 登录 | 立即注册

    本版积分规则

    QQ|手机版|Java学习者论坛 ( 声明:本站资料整理自互联网,用于Java学习者交流学习使用,对资料版权不负任何法律责任,若有侵权请及时联系客服屏蔽删除 )

    GMT+8, 2024-3-29 06:24 , Processed in 0.353045 second(s), 37 queries .

    Powered by Discuz! X3.4

    © 2001-2017 Comsenz Inc.

    快速回复 返回顶部 返回列表