IT俱乐部 Redis Redis @type坑的解决

Redis @type坑的解决

redis中@type导致取数据解析报错

java.lang.ClassCastException: com.alibaba.fastjson.JSONObject cannot be cast to
新建一个对象存入redis中,对象中会出现一个字段@type

LoginUser user = new LoginUser ()
......
redisTemplate.opsForValue().set(key, user)

存入redis中数据如下

127.0.0.1:6379> get login_tokens:5be4de32-6eb5-44a5-b212-56d93e3fc067
"{"@type":"com.common.core.domain.model.LoginUser","deptId":103L,"expireTime":1710463649132,"token":"xxxx","user":{"admin":true,"createBy":"admin","dept":{"deptId":103L,"deptName":"xxx","orderNum":1,"params":{"@type":"java.util.HashMap"},"parentId":101L,"status":"0"},"deptId":103L,"loginDate":"2024-03-14 14:35:56","loginIp":"127.0.0.1","nickName":"xxx","params":{"@type":"java.util.HashMap"},"phonenumber":"15888888888","sex":"1","status":"0","userId":1L,"userName":"admin"},"userId":1L,"username":"admin"}"
127.0.0.1:6379>

取数据时,redisTemplate.opsForValue().get(key);
如果LoginUser对象的包与存入时的包路径不一致,会报错java.lang.ClassCastException: com.alibaba.fastjson.JSONObject cannot be cast to

redis缓存序列化导致存储数据没有@type

在使用redis注解将数据缓存的时候发现存储进去的数据是这样的,没有@type

127.0.0.1:6379> get login_tokens:5be4de32-6eb5-44a5-b212-56d93e3fc067
"{"deptId":103L,"expireTime":1710463649132,"token":"xxxx","user":{"admin":true,"createBy":"admin","dept":{"deptId":103L,"deptName":"xxx","orderNum":1,"parentId":101L,"status":"0"},"deptId":103L,"loginDate":"2024-03-14 14:35:56","loginIp":"127.0.0.1","nickName":"xxx","phonenumber":"15888888888","sex":"1","status":"0","userId":1L,"userName":"admin"},"userId":1L,"username":"admin"}"
127.0.0.1:6379>

之前通过set方法放进去的数据是这样的

127.0.0.1:6379> get login_tokens:5be4de32-6eb5-44a5-b212-56d93e3fc067
"{"@type":"com.common.core.domain.model.LoginUser","deptId":103L,"expireTime":1710463649132,"token":"xxxx","user":{"admin":true,"createBy":"admin","dept":{"deptId":103L,"deptName":"xxx","orderNum":1,"params":{"@type":"java.util.HashMap"},"parentId":101L,"status":"0"},"deptId":103L,"loginDate":"2024-03-14 14:35:56","loginIp":"127.0.0.1","nickName":"xxx","params":{"@type":"java.util.HashMap"},"phonenumber":"15888888888","sex":"1","status":"0","userId":1L,"userName":"admin"},"userId":1L,"username":"admin"}"
127.0.0.1:6379>

原因:
是因为set方法的序列化方法和注解的序列化方法不同

解决办法:
将序列化方法更换成set方法所使用的序列化方法

下面是序列化方法

public class FastJson2JsonRedisSerializer implements RedisSerializer {
    @SuppressWarnings("unused")
    private ObjectMapper objectMapper = new ObjectMapper();

    public static final Charset DEFAULT_CHARSET = StandardCharsets.UTF_8;

    private Class clazz;

    static {
        ParserConfig.getGlobalInstance().setAutoTypeSupport(true);
    }

    public FastJson2JsonRedisSerializer(Class clazz) {
        super();
        this.clazz = clazz;
    }

    @Override
    public byte[] serialize(T t) throws SerializationException {
        if (t == null) {
            return new byte[0];
        }
        return JSON.toJSONString(t, SerializerFeature.WriteClassName).getBytes(DEFAULT_CHARSET);
    }

    @Override
    public T deserialize(byte[] bytes) throws SerializationException {
        if (bytes == null || bytes.length  clazz) {
        return TypeFactory.defaultInstance().constructType(clazz);
    }
}

SerializerFeature.WriteClassName这个序列化

public static String getString(Object object) {
   return JSON.toJSONString(object, SerializerFeature.WriteClassName);
}

如果加了SerializerFeature.WriteClassName存进redis当中的实体类就会带@type路径地址
“@type”:“com.xxx.xxx.entity.OpenNotice”

问题解决方案:去掉@type 或者 两边@type路径存放路径一致 (包名和实体类修改为一致)

去掉@type使用 JSONObject.toJSONString(obj)来存value实体类

    /**
     * hashMap存值方式
     *
     * @param parentKey
     * @param fieldKey
     * @param obj
     */
    public static void hashSet(String parentKey, String fieldKey, Object obj) {
        try {
            jedis.hset(parentKey, fieldKey, JSONObject.toJSONString(obj));
            //jedis.hset(parentKey, fieldKey, JSONParser.getString(obj)); //"@type":"com.xyz.miniLegion.entity.OpenNotice"
        } finally {
            jedis.close();
        }
    }

获取hashAll数据

   /**
     * 获取hashGetAll
     * @param parentKey
     * @return
     */
    public Map hashGetAll(String parentKey) {
        try (Jedis jedis = pools.getResource()) { //这种写法不需要手动close();
            return jedis.hgetAll(parentKey);
        }catch (Exception e) {      
            return null;
        }
    }

测试Redis转实体类`

   @Test
    void getSoldierAttribute() {
        Map openNoticeMap = redisPoolMgr.hashGetAll(StaticData.OpenNotice);
        //第一种根据key循环
        for (String key : openNoticeMap.keySet()) {
            OpenNotice openNotice = JSONObject.parseObject(openNoticeMap.get(key), OpenNotice.class);
            System.out.println("根据key循环:" +openNotice.getContent());
            System.out.println("根据key循环:" + JSONObject.toJSONString(openNotice));
        }
 
        //第二种根据value循环
        for (String values : openNoticeMap.values()) {
            OpenNotice openNotice = JSONObject.parseObject(values, OpenNotice.class);
            System.out.println("根据value循环:"+openNotice.getContent());
            System.out.println("根据value循环:" + JSONObject.toJSONString(openNotice));
        }
    }

 到此这篇关于Redis @type坑的解决的文章就介绍到这了,更多相关Redis @type坑内容请搜索IT俱乐部以前的文章或继续浏览下面的相关文章希望大家以后多多支持IT俱乐部!

本文收集自网络,不代表IT俱乐部立场,转载请注明出处。https://www.2it.club/database/redis/12039.html
上一篇
下一篇
联系我们

联系我们

在线咨询: QQ交谈

邮箱: 1120393934@qq.com

工作时间:周一至周五,9:00-17:30,节假日休息

关注微信
微信扫一扫关注我们

微信扫一扫关注我们

返回顶部