fastjson对象序列化的问题

news2024/9/28 1:19:43

今天偶然遇到一个fastjson将字符串反序列化为一个对象的时候的问题,就是简单的通过com.alibaba.fastjson.JSON将对象转为字符串,然后再从字符串转换为原类型的对象。

涉及的代码也非常简单

package cn.edu.sgu.www.mhxysy.service.role.impl;

import cn.edu.sgu.www.mhxysy.consts.RedisKeyPrefixConst;
import cn.edu.sgu.www.mhxysy.entity.role.AdvancedProperty;
import cn.edu.sgu.www.mhxysy.observe.observer.Observer;
import cn.edu.sgu.www.mhxysy.observe.subject.Subject;
import cn.edu.sgu.www.mhxysy.redis.StringRedisUtils;
import cn.edu.sgu.www.mhxysy.service.role.AdvancedPropertyService;
import com.alibaba.fastjson.JSON;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

/**
 * @author heyunlin
 * @version 1.0
 */
@Service
public class AdvancedPropertyServiceImpl implements AdvancedPropertyService {

    private final StringRedisUtils stringRedisUtils;
    private final Subject advancedPropertySubject;
    private final Observer advancedPropertyObserver;

    @Autowired
    public AdvancedPropertyServiceImpl(
            StringRedisUtils stringRedisUtils,
            Subject advancedPropertySubject,
            Observer advancedPropertyObserver) {
        this.stringRedisUtils = stringRedisUtils;
        this.advancedPropertySubject = advancedPropertySubject;
        this.advancedPropertyObserver = advancedPropertyObserver;
    }

    @Override
    public AdvancedProperty selectByRoleId(String roleId) {
        String key = RedisKeyPrefixConst.PREFIX_ADVANCED_PROPERTY + roleId;

        // 没有命中缓存
        if (!stringRedisUtils.hasKey(key)) {
            advancedPropertySubject.addObserver(advancedPropertyObserver);
            advancedPropertySubject.notice(roleId);
        }

        String data = stringRedisUtils.get(key);
        Object object = JSON.parse(data);

        return (AdvancedProperty) object;
    }

}

这里应用了观察者模式,如果查询没有命中缓存,就会主动触发主题的通知方法notice(),最后会调用具体观察者的update()方法

package cn.edu.sgu.www.mhxysy.observe.observer;

import cn.edu.sgu.www.mhxysy.consts.RedisKeyPrefixConst;
import cn.edu.sgu.www.mhxysy.dto.xingyin.XingyinAttributeDTO;
import cn.edu.sgu.www.mhxysy.entity.equipment.Equipment;
import cn.edu.sgu.www.mhxysy.entity.equipment.EquipmentTexiao;
import cn.edu.sgu.www.mhxysy.entity.role.AdvancedProperty;
import cn.edu.sgu.www.mhxysy.entity.xingyin.Xingyin;
import cn.edu.sgu.www.mhxysy.enums.WearStatus;
import cn.edu.sgu.www.mhxysy.mapper.baoshi.BaoshiMapper;
import cn.edu.sgu.www.mhxysy.mapper.equipment.EquipmentMapper;
import cn.edu.sgu.www.mhxysy.mapper.equipment.EquipmentTexiaoMapper;
import cn.edu.sgu.www.mhxysy.mapper.role.AdvancedPropertyMapper;
import cn.edu.sgu.www.mhxysy.mapper.xingyin.XingyinAttributeMapper;
import cn.edu.sgu.www.mhxysy.mapper.xingyin.XingyinMapper;
import cn.edu.sgu.www.mhxysy.redis.StringRedisUtils;
import cn.edu.sgu.www.mhxysy.vo.AttributeVO;
import cn.edu.sgu.www.mhxysy.vo.baoshi.BaoshiXiangqianVO;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * 具体观察者-角色高级属性观察者
 * @author heyunlin
 * @version 1.0
 */
@Component
public class AdvancedPropertyObserver implements Observer {

    private final BaoshiMapper baoshiMapper;
    private final XingyinMapper xingyinMapper;
    private final EquipmentMapper equipmentMapper;
    private final StringRedisUtils stringRedisUtils;
    private final EquipmentTexiaoMapper equipmentTexiaoMapper;
    private final XingyinAttributeMapper xingyinAttributeMapper;
    private final AdvancedPropertyMapper advancedPropertyMapper;

    @Autowired
    public AdvancedPropertyObserver(
            BaoshiMapper baoshiMapper,
            XingyinMapper xingyinMapper,
            EquipmentMapper equipmentMapper,
            StringRedisUtils stringRedisUtils,
            EquipmentTexiaoMapper equipmentTexiaoMapper,
            XingyinAttributeMapper xingyinAttributeMapper,
            AdvancedPropertyMapper advancedPropertyMapper) {
        this.baoshiMapper = baoshiMapper;
        this.xingyinMapper = xingyinMapper;
        this.equipmentMapper = equipmentMapper;
        this.stringRedisUtils = stringRedisUtils;
        this.equipmentTexiaoMapper = equipmentTexiaoMapper;
        this.xingyinAttributeMapper = xingyinAttributeMapper;
        this.advancedPropertyMapper = advancedPropertyMapper;
    }

    @Override
    public void update(Object message) {
        String roleId = (String) message;
        AdvancedProperty advancedProperty = advancedPropertyMapper.selectByRoleId(roleId);

        advancedProperty.setRoleId(roleId);

        /*
         * 物理暴击
         */
        AtomicInteger wlbj = new AtomicInteger(0);
        /*
         * 物理抗暴
         */
        AtomicInteger wlkb = new AtomicInteger(0);
        /*
         * 法术暴击
         */
        AtomicInteger fsbj = new AtomicInteger(0);
        /*
         * 法术抗暴
         */
        AtomicInteger fskb = new AtomicInteger(0);
        /*
         * 忽视物防
         */
        AtomicInteger hswf = new AtomicInteger(0);
        /*
         * 忽视法防
         */
        AtomicInteger hsff = new AtomicInteger(0);
        /*
         * 封印命中
         */
        AtomicInteger fymz = new AtomicInteger(0);
        /*
         * 抵抗封印
         */
        AtomicInteger dkfy = new AtomicInteger(advancedProperty.getDkfy());

        // 星印附加属性
        /*
         * 物暴伤害
         */
        AtomicInteger wbsh = new AtomicInteger(0);
        /*
         * 法暴伤害
         */
        AtomicInteger fbsh = new AtomicInteger(0);
        /*
         * 物理抵抗
         */
        AtomicInteger wldk = new AtomicInteger(0);
        /*
         * 法术抵抗
         */
        AtomicInteger fsdk = new AtomicInteger(0);
        /*
         * 回复强度
         */
        AtomicInteger hfqd = new AtomicInteger(0);

        // todo 查询高级属性并赋值
        // 查询角色穿戴的装备
        QueryWrapper<Equipment> wrapper = new QueryWrapper<>();

        wrapper.eq("role_id", roleId);
        wrapper.eq("wear_status", WearStatus.YCD.getValue());

        List<Equipment> list = equipmentMapper.selectList(wrapper);

        if(!list.isEmpty()) {
            // 装备特效增加的属性
            for (Equipment equipment : list) {
                EquipmentTexiao texiao = equipmentTexiaoMapper.selectById(equipment.getTexiaoId());

                java.lang.String name = texiao.getName();

                switch (name) {
                    case "物理暴击+1%":
                        wlbj.addAndGet(1);
                        break;
                    case "物理抗暴+2%":
                        wlkb.addAndGet(2);
                        break;
                    case "法术暴击+1%":
                        fsbj.addAndGet(1);
                        break;
                    case "法术抗暴+2%":
                        fsbj.addAndGet(2);
                        break;
                    case "封印命中+1%":
                        fymz.addAndGet(10);
                        break;
                    case "抵抗封印+1%":
                        dkfy.addAndGet(10);
                        break;
                    case "忽视物防+2%":
                        hswf.addAndGet(2);
                        break;
                    case "忽视法防+2%":
                        hsff.addAndGet(2);
                        break;
                    default:
                        break;
                }

                // 查询角色装备上镶嵌的宝石(红纹石:封印命中、神秘石:抵抗封印)
                List<BaoshiXiangqianVO> attributes = baoshiMapper.selectAttributes(equipment.getId());

                for (BaoshiXiangqianVO attribute : attributes) {
                    if ("抵抗封印".equals(attribute.getPropertyName())) {
                        dkfy.addAndGet(attribute.getGrade() * attribute.getPropertyValue());
                    } else if ("封印命中".equals(attribute.getPropertyName())) {
                        fymz.addAndGet(attribute.getGrade() * attribute.getPropertyValue());
                    }
                }
            }
        }

        // 查询角色穿戴的星印
        Map<java.lang.String, Object> map = new HashMap<>();

        map.put("role_id", roleId);
        map.put("wear_state", WearStatus.YCD.getValue());

        List<Xingyin> xingyinList = xingyinMapper.selectByMap(map);

        if (!xingyinList.isEmpty()) {
            // 获取星印的属性
            XingyinAttributeDTO xingyinAttributeDTO = new XingyinAttributeDTO();

            for (Xingyin xingyin : xingyinList) {
                xingyinAttributeDTO.setXingyinId(xingyin.getId());

                List<AttributeVO> attributes = xingyinAttributeMapper.selectAttributes(xingyinAttributeDTO);

                for (AttributeVO attribute : attributes) {
                    if ("气血回复效果".equals(attribute.getPropertyName())) {
                        hfqd.addAndGet(attribute.getPropertyValue());
                    } else if ("物理抵抗".equals(attribute.getPropertyName())) {
                        wldk.addAndGet(attribute.getPropertyValue());
                    } else if ("法术抵抗".equals(attribute.getPropertyName())) {
                        fsdk.addAndGet(attribute.getPropertyValue());
                    } else if ("封印命中".equals(attribute.getPropertyName())) {
                        fymz.addAndGet(attribute.getPropertyValue());
                    } else if ("抵抗封印".equals(attribute.getPropertyName())) {
                        dkfy.addAndGet(attribute.getPropertyValue());
                    } else if ("法术暴击伤害".equals(attribute.getPropertyName())) {
                        fbsh.addAndGet(attribute.getPropertyValue());
                    } else if ("物理暴击伤害".equals(attribute.getPropertyName())) {
                        wbsh.addAndGet(attribute.getPropertyValue());
                    }
                }
            }
        }

        advancedProperty.setWlbj(wlbj.get() + "%");
        advancedProperty.setWlkb(wlkb.get() + "%");
        advancedProperty.setFsbj(fsbj.get()  + "%");
        advancedProperty.setFskb(fskb.get()  + "%");
        advancedProperty.setHswf(hswf.get() + "%");
        advancedProperty.setHsff(hsff.get() + "%");
        advancedProperty.setFymz(fymz.get());
        advancedProperty.setDkfy(dkfy.get());
        advancedProperty.setWbsh(wbsh.get());
        advancedProperty.setFbsh(fbsh.get());
        advancedProperty.setWldk(wldk.get());
        advancedProperty.setFsdk(fsdk.get());
        advancedProperty.setHfqd(hfqd.get());

        // 保存到redis中
        String key = RedisKeyPrefixConst.PREFIX_ADVANCED_PROPERTY + roleId;

        stringRedisUtils.set(key, JSON.toJSONString(advancedProperty));
    }

}

而AdvancedProperty是一个数据库entity类

package cn.edu.sgu.www.mhxysy.entity.role;

import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;

import java.io.Serializable;

/**
 * 角色高级属性表
 * @author heyunlin
 * @version 1.0
 */
@Data
@TableName("advanced_property")
public class AdvancedProperty implements Serializable {
    private static final long serialVersionUID = 18L;

    /**
     * 角色ID
     */
    private String roleId;

    /**
     * 物理暴击
     */
    private String wlbj;

    /**
     * 物理抗暴
     */
    private String wlkb;

    /**
     * 法术暴击
     */
    private String fsbj;

    /**
     * 法术抗暴
     */
    private String fskb;

    /**
     * 忽视物防
     */
    private String hswf;

    /**
     * 忽视法防
     */
    private String hsff;

    /**
     * 封印命中
     */
    private Integer fymz;

    /**
     * 抵抗封印
     */
    private Integer dkfy;

    // 星印附加属性

    /**
     * 物暴伤害
     */
    private Integer wbsh;

    /**
     * 法暴伤害
     */
    private Integer fbsh;

    /**
     * 物理抵抗
     */
    private Integer wldk;

    /**
     * 法术抵抗
     */
    private Integer fsdk;

    /**
     * 回复强度
     */
    private Integer hfqd;
}

然后在查询数据的时候发生了类型转换异常。

 最后通过debug发现其实通过下面代码解析得到的对象的结构和AdvancedProperty是一样的

Object object = JSON.parse(data);

既然如此,不能转换类型,那就不转了呗,其实返回值的类型并不影响前端页面的数据渲染,所以把接口返回类型改为Object,问题完美解决~

package cn.edu.sgu.www.mhxysy.service.role.impl;

import cn.edu.sgu.www.mhxysy.consts.RedisKeyPrefixConst;
import cn.edu.sgu.www.mhxysy.observe.observer.Observer;
import cn.edu.sgu.www.mhxysy.observe.subject.Subject;
import cn.edu.sgu.www.mhxysy.redis.StringRedisUtils;
import cn.edu.sgu.www.mhxysy.service.role.AdvancedPropertyService;
import com.alibaba.fastjson.JSON;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

/**
 * @author heyunlin
 * @version 1.0
 */
@Service
public class AdvancedPropertyServiceImpl implements AdvancedPropertyService {

    private final StringRedisUtils stringRedisUtils;
    private final Subject advancedPropertySubject;
    private final Observer advancedPropertyObserver;

    @Autowired
    public AdvancedPropertyServiceImpl(
            StringRedisUtils stringRedisUtils,
            Subject advancedPropertySubject,
            Observer advancedPropertyObserver) {
        this.stringRedisUtils = stringRedisUtils;
        this.advancedPropertySubject = advancedPropertySubject;
        this.advancedPropertyObserver = advancedPropertyObserver;
    }

    @Override
    public Object selectByRoleId(String roleId) {
        String key = RedisKeyPrefixConst.PREFIX_ADVANCED_PROPERTY + roleId;

        // 没有命中缓存
        if (!stringRedisUtils.hasKey(key)) {
            advancedPropertySubject.addObserver(advancedPropertyObserver);
            advancedPropertySubject.notice(roleId);
        }

        String data = stringRedisUtils.get(key);

        return JSON.parse(data);
    }

}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1130470.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

单片机设计基于STM32的空气净化器设计

**单片机设计介绍&#xff0c;1615[毕设课设]基于STM32的空气净化器设计 文章目录 一 概要二、功能设计设计思路 三、 软件设计原理图pcb设计图 五、 程序六、 文章目录 一 概要 此设计资料主要包含原理图、PCB、源程序、元器件清等资料&#xff0c; 二、功能设计 设计思路 …

uniapp--点击上传图片到oss再保存数据给后端接口

项目采用uniapp与uview2.0组件库 --1.0的也可以参考一下&#xff0c;大差不差 一、项目要求与样式图 点击上传n张图片到oss&#xff0c;然后点击提交给后端 二、思路 1、打开上传按钮&#xff0c;弹出框内出现上传图片和提交按钮 2、点击上传图片区域&#xff0c;打开本地图…

redis持久化之AOF(Append Only File)

1 : AOF 是什么 以日志的形式来记录每个写操作&#xff08;增量保存&#xff09;&#xff0c;将redis执行过的所有写指令记录下来&#xff08;读操作不记 录&#xff09;&#xff0c;只允追加文件但不可改写文件&#xff0c;redis启动之初会读取该文件重新构造数据&#xff0c;…

【Linux】IP协议

文章目录 &#x1f4d6; 前言1. 网络层2. IP协议格式3. IP报文分片和组装3.1 如何分片和组装&#xff1a;3.2 组装的衍生问题&#xff1a; 4. 网段划分&#xff08;重点&#xff09;4.1 子网掩码&#xff1a;4.2 IP地址的数量限制&#xff1a;4.3 私有IP地址和公网IP地址&#…

读高性能MySQL(第4版)笔记19_云端和合规性

1. 如何构建数据库环境 1.1. 托管MySQL 1.2. VM上构建 1.3. 天下没有免费的午餐&#xff0c;每一个选择都伴随着一系列的权衡 2. 托管MySQL 2.1. 服务商提供了一个可访问的数据库设置程序&#xff0c;而不需要用户深入了解MySQL的具体细节 2.2. 使用托管MySQL将缺乏很多的…

vueDay03——计算属性

一、一般场景 当我们需要对某个数据进行简单判断渲染的时候&#xff0c;我们通常会使用如下方法 <div>nginx当前状态&#xff1a;{{ openNginx true ? true : false}} </div> 但是这样就很影响观感&#xff0c;因为渲染出来的只有openNginx的值&#xff0c;而…

微信小程序投票管理系统:打造智能、便捷的投票体验

前言 随着社交网络的兴起和移动互联网的普及&#xff0c;人们对于参与和表达意见的需求越来越强烈。在这个背景下&#xff0c;微信小程序投票管理系统应运而生。它为用户提供了一个智能、便捷的投票平台&#xff0c;使用户可以轻松创建和参与各种类型的投票活动。本文将详细介…

【C++学习笔记】类和对象(上)

目录 1. 面向对象和面向过程的初步认识 2. 类的引入 3. 类的定义 3.1 类的两种定义方式 3.1.1声明和定义全部放在类体中 3.1.2.类声明放在.h文件中&#xff0c;成员函数定义放在.cpp文件中 4. 类的访问限定符及封装 4.1 访问限定符 4.2 面试题&#xff1a;C中struct…

百度文心一言4.0——使用及API测试

登录百度智能云&#xff1a;百度智能云 文心一言4.0使用 开通付费&#xff1a; 创建应用&#xff1a; 自行创建应用名称&#xff1a; 对话测试&#xff1a; API测试 ERNIE-Bot-4 API&#xff1a;ERNIE-Bot-4 打开链接查看自己的API Key&#xff0c;Secret Key。 可参…

Python手搓C4.5决策树+Azure Adult数据集分析

前言 课上的实验 由于不想被抄袭&#xff0c;所以暂时不放完整代码 Adult数据集可以在Azure官网上找到 Azure 开放数据集中的数据集 - Azure Open Datasets | Microsoft Learn 数据集预处理 删除难以处理的权重属性fnlwgt与意义重复属性educationNum去除重复行与空行删除…

从一个页面跳转到目标页面之后,对应的顶部路由高亮

需求&#xff1a;页面跳转到目标页面之后&#xff0c;对应的顶部路由高亮 上面的更多 跳转到 学情分析下面的学生分析 <template><div class"topBar" ref"topBar" v-loading.fullscreen.lock"fullscreenLoading"><div class&quo…

dc9靶机攻略

dc9 扫描 扫描结果如图 nmap 目录扫描 指纹扫描 渗透 访问首页 该处发现搜索框&#xff0c;正常搜名字可以直接返回该用户的信息&#xff0c;怀疑sql注入&#xff0c;使用单引号注入&#xff0c;发现没反应&#xff0c;再使用一下万能注入语句1 or 11 使用sqlmap sqlmap -…

什么是蓝桥杯?什么是蓝桥STEMA考试?

第十五届蓝桥大赛赛事安排? STEMA考试11月(考试时间11月26日) STEMA考试1月(2024年1月) STEMA考试3月(2024年3月) 第十五届蓝桥杯省赛(2024年4月待定) 第十五届蓝桥杯国赛(2024年5月待定) 注:以上时间具体以组委会官方发布为准。 01.蓝桥杯 蓝桥杯全国软件和…

【每日一题】掷骰子等于目标和的方法数

文章目录 Tag题目来源题目解读解题思路方法一&#xff1a;动态规划 写在最后 Tag 【动态规划】【数组】 题目来源 1155. 掷骰子等于目标和的方法数 题目解读 你手里有 n 个一样的骰子&#xff0c;每个骰子都有 k 个面&#xff0c;分别标号 1 到 n。给定三个整数 n&#xff0…

部署基于efk+logstash+kafka构建日志收集平台并对nginx日志进行分析

文章目录 1.1 安装zookeeper集群1.2 安装kafka集群1.3 部署filebeat服务1.4 部署logstash1.5 部署es和kibana服务1.6 配置kibana ui界面1.7 对nginx进行日志分析 Filebeat采集日志kafka topic存起来日志->logstash去kafka获取日志&#xff0c;进行格式转换->elasticsearc…

【计算机网络笔记】网络应用进程通信

系列文章目录 什么是计算机网络&#xff1f; 什么是网络协议&#xff1f; 计算机网络的结构 数据交换之电路交换 数据交换之报文交换和分组交换 分组交换 vs 电路交换 计算机网络性能&#xff08;1&#xff09;——速率、带宽、延迟 计算机网络性能&#xff08;2&#xff09;…

【RocketMQ系列十四】RocketMQ中消息堆积如何处理

您好&#xff0c;我是码农飞哥&#xff08;wei158556&#xff09;&#xff0c;感谢您阅读本文&#xff0c;欢迎一键三连哦。 &#x1f4aa;&#x1f3fb; 1. Python基础专栏&#xff0c;基础知识一网打尽&#xff0c;9.9元买不了吃亏&#xff0c;买不了上当。 Python从入门到精…

Elasticsearch分词器-中文分词器ik

文章目录 使用standard analysis对英文进行分词使用standard analysis对中文进行分词安装插件对中文进行友好分词-ik中文分词器下载安装和配置IK分词器使用ik_smart分词器使用ik_max_word分词器 text analysis 使用standard analysis对英文进行分词 ES默认使用standard analys…

【Java】智慧医院绩效考核系统源码

医院绩效考核系统使用JAVA语言开发&#xff0c;采用B/S架构模式设计&#xff0c;后台使用MySql数据库进行管理的一整套计算机应用软件。系统和his系统进行对接&#xff0c;按照设定周期&#xff0c;从his系统获取医院科室和医生、护士、其他人员工作量&#xff0c;对没有录入信…

【MySQL架构篇】逻辑架构

逻辑架构 文章目录 逻辑架构1. 服务器处理客户端请求2. Connectors3. 第一层&#xff1a;连接层4. 第二层&#xff1a;服务层5. 第三层&#xff1a;存储引擎6. 存储层7. 小结 1. 服务器处理客户端请求 首先 MySQL 是典型的 C/S 架构&#xff0c;即 Client/Server 架构&#xf…