Redis获取数据转json,解决动态泛型传参

本文涉及的产品
Redis 开源版,标准版 2GB
推荐场景:
搭建游戏排行榜
云数据库 Tair(兼容Redis),内存型 2GB
简介: 项目有两种角色需要不同的登录权限,将redis做为用户登录信息缓存数据库。码一个方法,希望能够根据传入不用用户实体类型来获取相应的数据。用户实体为:SessionEntity<User1>、SessionEntity<User2>。json使用FastJson。

 场景:项目有两种角色需要不同的登录权限,将redis做为用户登录信息缓存数据库。码一个方法,希望能够根据传入不用用户实体类型来获取相应的数据。用户实体为:SessionEntity<User1>、SessionEntity<User2>。json使用FastJson。

先阐述遇到的几个问题:

1、redis获取到的数据序列化后,转json,经常提示转换异常(并不是每次,只是时常)。

2、不想每种用户都书写一个redis操作方法(显得tai low)。

解决:

1、redis获取到的数据序列化后,转json,经常提示转换异常:

   先说redis有两种获取方式。

1)

redisTemplate.opsForValue().get(key);

image.gif

2)

SessionEntity result = redisTemplate.execute(new RedisCallback<SessionEntity>() {
            public SessionEntity doInRedis(RedisConnection connection)
                    throws DataAccessException {
                RedisSerializer<String> serializer = getRedisSerializer();
                byte[] key = serializer.serialize(s);
                byte[] value = connection.get(key);
                if (value == null) {
                    return null;
                }
                String json = serializer.deserialize(value);
                return JSONObject.parseObject(json,SessionEntity.class);
            }
        });

image.gif

显然第一种的方式比较简单。查看源码,发现第一种方式底层调用的也是redisTemplate.execute方法,所以应该算是一种封装吧。我们一直采用的是第二种方式。(第一种方式试过,也一样会出现json强转异常)。这里出现过json异常,怀疑是跟泛型有关。这里手动指定泛型反序列化类型。

修改后:

SessionEntity result = redisTemplate.execute(new RedisCallback<SessionEntity>() {
            public SessionEntity doInRedis(RedisConnection connection)
                    throws DataAccessException {
                RedisSerializer<String> serializer = getRedisSerializer();
                byte[] key = serializer.serialize(s);
                byte[] value = connection.get(key);
                if (value == null) {
                    return null;
                }
                String json = serializer.deserialize(value);
                return JSONObject.parseObject(json, new TypeReference<SessionEntity<User>>(){});
            }
        });

image.gif

完美~,确实解决了json强转异常。

那么问题来了,这里的TypeReference需要手动指定明确的的实体类型,尝试添加泛型:

SessionEntity<T> result = redisTemplate.execute(new RedisCallback<SessionEntity<T>>() {
            public SessionEntity<T> doInRedis(RedisConnection connection)
                    throws DataAccessException {
                RedisSerializer<String> serializer = getRedisSerializer();
                byte[] key = serializer.serialize(s);
                byte[] value = connection.get(key);
                if (value == null) {
                    return null;
                }
                String json = serializer.deserialize(value);
                return JSONObject.parseObject(json, new TypeReference<SessionEntity<T>>(){});
            }
        });

image.gif

看样子是没什么问题,而且泛型也被识别到了。 但是依旧无法通过。

2、不想每种用户都书写一个redis操作方法:

上面说到就算加了泛型也依旧无法通过,尝试了多种方式依旧如此。百度了一圈,都是说使用TypeReference这个来解决,但是并没有提及动态泛型的问题。偶然间看到文章说Fastjson不支持,所以尝试替换成jackson。

替换后的代码:

SessionEntity<T> result = redisTemplate.execute(new RedisCallback<SessionEntity<T>>() {
            public SessionEntity<T> doInRedis(RedisConnection connection)
                    throws DataAccessException {
                RedisSerializer<String> serializer = getRedisSerializer();
                byte[] key = serializer.serialize(s);
                byte[] value = connection.get(key);
                if (value == null) {
                    return null;
                }
                String json = serializer.deserialize(value);
                ObjectMapper om = new ObjectMapper();
                JavaType javatype = om.getTypeFactory().constructParametricType(SessionEntity.class, clazz);
                try {
                    return om.readValue(json, javatype);
                } catch (IOException e) {
                    e.printStackTrace();
                }
                return null;
//                return JSONObject.parseObject(json, new TypeReference<SessionEntity<T>>(){});
            }
        });

image.gif

这里使用到了jackson的ObjectMapper。ObjectMapper类是Jackson库的主要类。它提供一些功能将转换成Java对象匹配JSON结构,反之亦然。它使用JsonParser和JsonGenerator的实例实现JSON实际的读/写。(复制来的)发现问题解决。

提供的抽象方法为:

public <T> SessionEntity<T> get(final String s, Class<T> clazz);

调用方式为:

sessionEntityDao.get(key, User1.class); 跟 sessionEntityDao.get(key, User2.class);

由于这里使用到的是jackson-databind-2.6.0的库,这个版本种constructParametricType这个方法已经快要过时,更高版本使用

constructParametrizedType

替换。这里我还没尝试过,等有空再玩。

这里问题已经解决,纯粹做个笔记以供自己以后方便查阅。这里只提供自己项目中遇到的解决方式之一,相信应该还有其他方式可以解决。如果有说明错误的地方,请指出并见谅。


相关实践学习
基于Redis实现在线游戏积分排行榜
本场景将介绍如何基于Redis数据库实现在线游戏中的游戏玩家积分排行榜功能。
云数据库 Redis 版使用教程
云数据库Redis版是兼容Redis协议标准的、提供持久化的内存数据库服务,基于高可靠双机热备架构及可无缝扩展的集群架构,满足高读写性能场景及容量需弹性变配的业务需求。 产品详情:https://www.aliyun.com/product/kvstore &nbsp; &nbsp; ------------------------------------------------------------------------- 阿里云数据库体验:数据库上云实战 开发者云会免费提供一台带自建MySQL的源数据库&nbsp;ECS 实例和一台目标数据库&nbsp;RDS实例。跟着指引,您可以一步步实现将ECS自建数据库迁移到目标数据库RDS。 点击下方链接,领取免费ECS&amp;RDS资源,30分钟完成数据库上云实战!https://developer.aliyun.com/adc/scenario/51eefbd1894e42f6bb9acacadd3f9121?spm=a2c6h.13788135.J_3257954370.9.4ba85f24utseFl
相关文章
|
19天前
|
NoSQL Redis
Redis的数据淘汰策略有哪些 ?
Redis 提供了 8 种数据淘汰策略,分为淘汰易失数据和淘汰全库数据两大类。易失数据淘汰策略包括:volatile-lru、volatile-lfu、volatile-ttl 和 volatile-random;全库数据淘汰策略包括:allkeys-lru、allkeys-lfu 和 allkeys-random。此外,还有 no-eviction 策略,禁止驱逐数据,当内存不足时新写入操作会报错。
49 16
|
2月前
|
监控 NoSQL Java
场景题:百万数据插入Redis有哪些实现方案?
场景题:百万数据插入Redis有哪些实现方案?
43 1
场景题:百万数据插入Redis有哪些实现方案?
|
19天前
|
缓存 NoSQL 关系型数据库
Redis和Mysql如何保证数据⼀致?
在项目中,为了解决Redis与Mysql的数据一致性问题,我们采用了多种策略:对于低一致性要求的数据,不做特别处理;时效性数据通过设置缓存过期时间来减少不一致风险;高一致性但时效性要求不高的数据,利用MQ异步同步确保最终一致性;而对一致性和时效性都有高要求的数据,则采用分布式事务(如Seata TCC模式)来保障。
53 14
|
19天前
|
存储 NoSQL 算法
Redis分片集群中数据是怎么存储和读取的 ?
Redis集群采用哈希槽分区算法,共有16384个哈希槽,每个槽分配到不同的Redis节点上。数据操作时,通过CRC16算法对key计算并取模,确定其所属的槽和对应的节点,从而实现高效的数据存取。
44 13
|
19天前
|
存储 NoSQL Redis
Redis的数据过期策略有哪些 ?
Redis 采用两种过期键删除策略:惰性删除和定期删除。惰性删除在读取键时检查是否过期并删除,对 CPU 友好但可能积压大量过期键。定期删除则定时抽样检查并删除过期键,对内存更友好。默认每秒扫描 10 次,每次检查 20 个键,若超过 25% 过期则继续检查,单次最大执行时间 25ms。两者结合使用以平衡性能和资源占用。
42 11
|
19天前
|
监控 NoSQL 测试技术
【赵渝强老师】Redis的AOF数据持久化
Redis 是内存数据库,提供数据持久化功能,支持 RDB 和 AOF 两种方式。AOF 以日志形式记录每个写操作,支持定期重写以压缩文件。默认情况下,AOF 功能关闭,需在 `redis.conf` 中启用。通过 `info` 命令可监控 AOF 状态。AOF 重写功能可有效控制文件大小,避免性能下降。
|
19天前
|
存储 监控 NoSQL
【赵渝强老师】Redis的RDB数据持久化
Redis 是内存数据库,提供数据持久化功能以防止服务器进程退出导致数据丢失。Redis 支持 RDB 和 AOF 两种持久化方式,其中 RDB 是默认的持久化方式。RDB 通过在指定时间间隔内将内存中的数据快照写入磁盘,确保数据的安全性和恢复能力。RDB 持久化机制包括创建子进程、将数据写入临时文件并替换旧文件等步骤。优点包括适合大规模数据恢复和低数据完整性要求的场景,但也有数据完整性和一致性较低及备份时占用内存的缺点。
|
2月前
|
数据采集 JSON 数据处理
抓取和分析JSON数据:使用Python构建数据处理管道
在大数据时代,电商网站如亚马逊、京东等成为数据采集的重要来源。本文介绍如何使用Python结合代理IP、多线程等技术,高效、隐秘地抓取并处理电商网站的JSON数据。通过爬虫代理服务,模拟真实用户行为,提升抓取效率和稳定性。示例代码展示了如何抓取亚马逊商品信息并进行解析。
抓取和分析JSON数据:使用Python构建数据处理管道
|
22天前
|
JSON 数据格式 索引
Python中序列化/反序列化JSON格式的数据
【11月更文挑战第4天】本文介绍了 Python 中使用 `json` 模块进行序列化和反序列化的操作。序列化是指将 Python 对象(如字典、列表)转换为 JSON 字符串,主要使用 `json.dumps` 方法。示例包括基本的字典和列表序列化,以及自定义类的序列化。反序列化则是将 JSON 字符串转换回 Python 对象,使用 `json.loads` 方法。文中还提供了具体的代码示例,展示了如何处理不同类型的 Python 对象。
|
26天前
|
JSON 缓存 前端开发
PHP如何高效地处理JSON数据:从编码到解码
在现代Web开发中,JSON已成为数据交换的标准格式。本文探讨了PHP如何高效处理JSON数据,包括编码和解码的过程。通过简化数据结构、使用优化选项、缓存机制及合理设置解码参数等方法,可以显著提升JSON处理的性能,确保系统快速稳定运行。