前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Redis获取数据转json,解决动态泛型传参

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

作者头像
有一只柴犬
发布2024-01-25 10:49:07
1610
发布2024-01-25 10:49:07
举报
文章被收录于专栏:JAVA体系

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

先阐述遇到的几个问题:

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

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

解决:

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

    先说redis有两种获取方式。

1)

代码语言:javascript
复制
redisTemplate.opsForValue().get(key);

2)

代码语言:javascript
复制
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);
            }
        });

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

修改后:

代码语言:javascript
复制
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>>(){});
            }
        });

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

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

代码语言:javascript
复制
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>>(){});
            }
        });

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

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

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

替换后的代码:

代码语言:javascript
复制
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>>(){});
            }
        });

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

提供的抽象方法为:

代码语言:javascript
复制
public <T> SessionEntity<T> get(final String s, Class<T> clazz);

调用方式为:

代码语言:javascript
复制
sessionEntityDao.get(key, User1.class); 跟 sessionEntityDao.get(key, User2.class);

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

代码语言:javascript
复制
constructParametrizedType

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

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

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2024-01-25,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
相关产品与服务
云数据库 Redis
腾讯云数据库 Redis(TencentDB for Redis)是腾讯云打造的兼容 Redis 协议的缓存和存储服务。丰富的数据结构能帮助您完成不同类型的业务场景开发。支持主从热备,提供自动容灾切换、数据备份、故障迁移、实例监控、在线扩容、数据回档等全套的数据库服务。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档