缓存类CacheDataManager把临时数据存入json。做成插件·

c 复制代码
#ifndef CACHEDATAMANAGER_H
#define CACHEDATAMANAGER_H

#if defined(QTFRAMEWORKHOST_LIBRARY)
#  define QTFRAMEWORKHOST_EXPORT Q_DECL_EXPORT
#else
#  define QTFRAMEWORKHOST_EXPORT Q_DECL_IMPORT
#endif

#include <QMap>
#include <QString>
#include <QVariant>

/*!
 * @class   CacheDataManager
 * @brief   全局数据管理器,缓存临时配置数据、保存配置文件
 *          需要获取实时修改信息,请订阅主题为CacheDataChangedEvent关键字为group的事件
 * @author  zhoubo
 * @version 1.0.1
 */
class QTFRAMEWORKHOST_EXPORT CacheDataManager
{   
public:
    /*!
     * @name    addCacheData
     * @brief   设置或更新需要缓存的信息
     * @param   group->组信息(不要包含特殊字符)
     * @param   key->关键字(不要包含特殊字符)
     * @param   value->对应值
     * @param   issave->是否保存到文件中,保存后下次会自动导入
     * @param   modifyKey->修改秘钥,只有使用相同秘钥才能被修改
     * @return  是否添加成功,如果失败可能是修改秘钥错误导致
     */
    virtual bool addCacheData(const QString &group,const QString &key,const QVariant &value,bool issave = false,QString modifyKey="*")=0;
    /*!
     * @name    addCacheData
     * @brief   设置或更新需要缓存的信息
     * @param   group->组信息(不要包含特殊字符)
     * @param   value->设置或更新的键值对,key关键字(不要包含特殊字符)
     * @param   issave->是否保存到文件中,保存后下次会自动导入
     * @param   modifyKey->修改秘钥,只有使用相同秘钥才能被修改
     */
    virtual void addCacheData(const QString &group,const QMap<QString,QVariant> &value,bool issave = false,QString modifyKey="*")=0;
    /*!
     * @name    cacheData
     * @brief   获取其他数据
     * @param   key->关键字
     * @param   value->对应值
     * @return  存在key为true,否则为false
     */
    virtual bool cacheData(const QString &group,const QString &key,QVariant &value)=0;
    /*!
     * @name    cacheData
     * @brief   获取其他数据
     * @param   key->关键字
     * @param   group->组名
     * @return  值
     */
    virtual QVariant cacheData(const QString &group,const QString &key)=0;
    /*!
     * @name    cacheData
     * @brief   获取group下的配置信息
     * @param   group->组名
     * @return  所有其他数据
     */
    virtual QMap<QString,QVariant> cacheData(const QString &group)=0;
    /*!
     * @name    remove
     * @brief   移除数据,只能移除修改秘钥为*的项
     */
    virtual void remove()=0;
    /*!
     * @name    remove
     * @brief   移除数据
     * @param   group->组名
     * @param   modifyKey->修改秘钥,只有使用相同秘钥才能被删除
     * @return  移除为true,否则为false
     */
    virtual bool remove(const QString &group,const QString modifyKey="*")=0;
    /*!
     * @name    remove
     * @brief   移除数据
     * @param   group->组名
     * @param   key->关键字
     * @param   modifyKey->修改秘钥,只有使用相同秘钥才能被删除
     * @return  移除为true,否则为false
     */
    virtual bool remove(const QString &group,const QString &key,const QString modifyKey="*")=0;
    /*!
     * @name    groups
     * @brief   获取所有组名称
     * @return  所有组名称
     */
    virtual QStringList groups()=0;
    /*!
     * @name    begingroups
     * @brief   获取以begin开始的所有组名称
     * @param   begin->以begin结尾的所有组
     * @return  所有组名称
     */
    virtual QStringList begingroups(const QString &begin)=0;
    /*!
     * @name    endgroups
     * @brief   获取以end结尾的所有组名称
     * @param   end->以end结尾的所有组
     * @return  所有组名称
     */
    virtual QStringList endgroups(const QString &end)=0;
    /*!
     * @name    keys
     * @brief   获取group所有关键字
     * @param   group->组名
     * @return  组中所有关键字
     */
    virtual QStringList keys(const QString& group)=0;
    /*!
     * @name    instance
     * @brief   获取CacheDataManager的实例
     * @return  CacheDataManager的实例
     */
    static CacheDataManager* instance();
};

#endif // CACHEDATAMANAGER_H
c 复制代码
#include "cachedatamanager.h"
#include <QFile>
#include <QJsonDocument>
#include <QJsonObject>
#include <QJsonArray>
#include <QMutex>
#include <QRegularExpression>

namespace {

/**
 * @brief 内部实现类,仅cpp文件可见,不对外导出
 */
class CacheDataManagerImpl : public CacheDataManager
{
public:
    CacheDataManagerImpl();
    ~CacheDataManagerImpl() override;

    bool addCacheData(const QString &group, const QString &key, const QVariant &value, bool issave, QString modifyKey) override;
    void addCacheData(const QString &group, const QMap<QString, QVariant> &value, bool issave, QString modifyKey) override;
    bool cacheData(const QString &group, const QString &key, QVariant &value) override;
    QVariant cacheData(const QString &group, const QString &key) override;
    QMap<QString, QVariant> cacheData(const QString &group) override;
    void remove() override;
    bool remove(const QString &group, const QString modifyKey) override;
    bool remove(const QString &group, const QString &key, const QString modifyKey) override;
    QStringList groups() override;
    QStringList begingroups(const QString &begin) override;
    QStringList endgroups(const QString &end) override;
    QStringList keys(const QString &group) override;

private:
    mutable QMutex m_mutex;

    /// group -> key -> <value, modifyKey>
    QMap<QString, QMap<QString, QPair<QVariant, QString>>> m_memoryData;
    /// 需要持久化保存的标记 group/key
    QSet<QString> m_saveMark;

    QString getSaveFilePath() const;
    void loadFromFile();
    void saveToFile();
    void notifyDataChanged(const QString &group);
    bool checkGroupNameValid(const QString &group);
    bool checkKeyNameValid(const QString &key);
};

static CacheDataManagerImpl* g_instance = nullptr;
static QMutex g_instanceMutex;

CacheDataManagerImpl::CacheDataManagerImpl()
{
    loadFromFile();
}

CacheDataManagerImpl::~CacheDataManagerImpl()
{
    saveToFile();
}

bool CacheDataManagerImpl::addCacheData(const QString &group, const QString &key, const QVariant &value, bool issave, QString modifyKey)
{
    QMutexLocker lock(&m_mutex);

    if(!checkGroupNameValid(group) || !checkKeyNameValid(key))
        return false;

    auto &groupData = m_memoryData[group];
    QString fullKey = QString("%1||%2").arg(group, key);

    // 如果该key已存在,校验modifyKey
    if(groupData.contains(key))
    {
        QString existModifyKey = groupData[key].second;
        if(existModifyKey != "*" && existModifyKey != modifyKey)
        {
            return false; //秘钥不匹配,禁止修改
        }
    }

    groupData[key] = qMakePair(value, modifyKey);

    if(issave)
    {
        m_saveMark.insert(fullKey);
        saveToFile();
    }

    notifyDataChanged(group);
    return true;
}

void CacheDataManagerImpl::addCacheData(const QString &group, const QMap<QString, QVariant> &value, bool issave, QString modifyKey)
{
    QMutexLocker lock(&m_mutex);
    if(!checkGroupNameValid(group))
        return;

    auto &groupData = m_memoryData[group];
    for(auto iter = value.cbegin(); iter != value.cend(); ++iter)
    {
        const QString &k = iter.key();
        if(!checkKeyNameValid(k))
            continue;

        QString fullKey = QString("%1||%2").arg(group, k);
        if(groupData.contains(k))
        {
            QString existMK = groupData[k].second;
            if(existMK != "*" && existMK != modifyKey)
                continue;
        }
        groupData[k] = qMakePair(iter.value(), modifyKey);
        if(issave)
        {
            m_saveMark.insert(fullKey);
        }
    }

    if(issave)
        saveToFile();

    notifyDataChanged(group);
}

bool CacheDataManagerImpl::cacheData(const QString &group, const QString &key, QVariant &value)
{
    QMutexLocker lock(&m_mutex);
    if(!m_memoryData.contains(group))
        return false;
    auto &g = m_memoryData[group];
    if(!g.contains(key))
        return false;

    value = g[key].first;
    return true;
}

QVariant CacheDataManagerImpl::cacheData(const QString &group, const QString &key)
{
    QMutexLocker lock(&m_mutex);
    if(!m_memoryData.contains(group))
        return QVariant();
    auto &g = m_memoryData[group];
    if(!g.contains(key))
        return QVariant();
    return g[key].first;
}

QMap<QString, QVariant> CacheDataManagerImpl::cacheData(const QString &group)
{
    QMutexLocker lock(&m_mutex);
    QMap<QString, QVariant> ret;
    if(!m_memoryData.contains(group))
        return ret;

    auto &g = m_memoryData[group];
    for(auto iter = g.cbegin(); iter != g.cend(); ++iter)
    {
        ret.insert(iter.key(), iter.value().first);
    }
    return ret;
}

void CacheDataManagerImpl::remove()
{
    QMutexLocker lock(&m_mutex);
    QStringList groupList = groups();
    for(const auto& g : groupList)
    {
        remove(g, "*");
    }
}

bool CacheDataManagerImpl::remove(const QString &group, const QString modifyKey)
{
    QMutexLocker lock(&m_mutex);
    if(!m_memoryData.contains(group))
        return false;

    auto &groupData = m_memoryData[group];
    bool anyRemoved = false;
    QStringList delKeys;

    for(auto iter = groupData.begin(); iter != groupData.end(); ++iter)
    {
        const QString &existMK = iter.value().second;
        if(existMK == "*" || existMK == modifyKey)
        {
            QString fullKey = QString("%1||%2").arg(group, iter.key());
            m_saveMark.remove(fullKey);
            delKeys << iter.key();
            anyRemoved = true;
        }
    }

    for(const auto& k : delKeys)
    {
        groupData.remove(k);
    }
    if(groupData.isEmpty())
    {
        m_memoryData.remove(group);
    }

    if(anyRemoved)
    {
        saveToFile();
        notifyDataChanged(group);
    }
    return anyRemoved;
}

bool CacheDataManagerImpl::remove(const QString &group, const QString &key, const QString modifyKey)
{
    QMutexLocker lock(&m_mutex);
    if(!m_memoryData.contains(group))
        return false;
    auto &groupData = m_memoryData[group];
    if(!groupData.contains(key))
        return false;

    QString existMK = groupData[key].second;
    if(existMK != "*" && existMK != modifyKey)
        return false;

    QString fullKey = QString("%1||%2").arg(group, key);
    m_saveMark.remove(fullKey);
    groupData.remove(key);
    if(groupData.isEmpty())
    {
        m_memoryData.remove(group);
    }

    saveToFile();
    notifyDataChanged(group);
    return true;
}

QStringList CacheDataManagerImpl::groups()
{
    QMutexLocker lock(&m_mutex);
    return m_memoryData.keys();
}

QStringList CacheDataManagerImpl::begingroups(const QString &begin)
{
    QMutexLocker lock(&m_mutex);
    QStringList ret;
    const auto& gs = m_memoryData.keys();
    for(const auto& g : gs)
    {
        if(g.startsWith(begin))
            ret << g;
    }
    return ret;
}

QStringList CacheDataManagerImpl::endgroups(const QString &end)
{
    QMutexLocker lock(&m_mutex);
    QStringList ret;
    const auto& gs = m_memoryData.keys();
    for(const auto& g : gs)
    {
        if(g.endsWith(end))
            ret << g;
    }
    return ret;
}

QStringList CacheDataManagerImpl::keys(const QString &group)
{
    QMutexLocker lock(&m_mutex);
    if(!m_memoryData.contains(group))
        return {};
    return m_memoryData[group].keys();
}

QString CacheDataManagerImpl::getSaveFilePath() const
{
    // 可修改为你实际缓存文件路径,示例程序运行目录cache.json
    return "./cacheData.json";
}

void CacheDataManagerImpl::loadFromFile()
{
    QFile f(getSaveFilePath());
    if(!f.open(QIODevice::ReadOnly))
        return;

    QJsonDocument doc = QJsonDocument::fromJson(f.readAll());
    f.close();
    if(!doc.isObject())
        return;

    QJsonObject root = doc.object();
    for(auto groupIter = root.begin(); groupIter != root.end(); ++groupIter)
    {
        QString group = groupIter.key();
        QJsonObject groupObj = groupIter.value().toObject();
        for(auto keyIter = groupObj.begin(); keyIter != groupObj.end(); ++keyIter)
        {
            QString key = keyIter.key();
            QJsonObject itemObj = keyIter.value().toObject();
            QVariant val = itemObj["value"].toVariant();
            QString mk = itemObj["modifyKey"].toString("*");
            bool saveFlag = itemObj["issave"].toBool(false);

            m_memoryData[group][key] = qMakePair(val, mk);
            if(saveFlag)
            {
                m_saveMark.insert(QString("%1||%2").arg(group, key));
            }
        }
    }
}

void CacheDataManagerImpl::saveToFile()
{
    QJsonObject root;
    for(auto gIter = m_memoryData.cbegin(); gIter != m_memoryData.cend(); ++gIter)
    {
        QString group = gIter.key();
        QJsonObject groupObj;
        auto &gData = gIter.value();
        for(auto kIter = gData.cbegin(); kIter != gData.cend(); ++kIter)
        {
            QString key = kIter.key();
            auto p = kIter.value();
            QString fullKey = QString("%1||%2").arg(group, key);
            QJsonObject item;
            item["value"] = QJsonValue::fromVariant(p.first);
            item["modifyKey"] = p.second;
            item["issave"] = m_saveMark.contains(fullKey);
            groupObj[key] = item;
        }
        root[group] = groupObj;
    }

    QJsonDocument doc(root);
    QFile f(getSaveFilePath());
    if(f.open(QIODevice::WriteOnly))
    {
        f.write(doc.toJson(QJsonDocument::Indented));
        f.close();
    }
}

void CacheDataManagerImpl::notifyDataChanged(const QString &group)
{
    // ========= 这里替换为你项目内部事件发送代码 =========
    // 文档注释:订阅主题为CacheDataChangedEvent,关键字为group的事件
    // eventBus->publish("CacheDataChangedEvent", group);
    // =================================================
    Q_UNUSED(group);
}

bool CacheDataManagerImpl::checkGroupNameValid(const QString &group)
{
    //禁止特殊字符 \ / : * ? " < > |
    static QRegularExpression reg(R"([\\/:*?"<>|])");
    return !group.contains(reg) && !group.isEmpty();
}

bool CacheDataManagerImpl::checkKeyNameValid(const QString &key)
{
    static QRegularExpression reg(R"([\\/:*?"<>|])");
    return !key.contains(reg) && !key.isEmpty();
}

} // end anonymous namespace

CacheDataManager* CacheDataManager::instance()
{
    QMutexLocker lock(&g_instanceMutex);
    if(!g_instance)
    {
        g_instance = new CacheDataManagerImpl();
    }
    return g_instance;
}

外部调用

c 复制代码
#include "cachedatamanager.h"

//设置缓存
CacheDataManager* cache = CacheDataManager::instance();
cache->addCacheData("sysConfig","name","testApp",true,"admin");

//读取
QVariant v = cache->cacheData("sysConfig","name");

//删除,必须匹配modifyKey
cache->remove("sysConfig","admin");

最好找个头文件

c 复制代码
/*! 临时缓存与配置宏定义 */
#define __AddCacheData CacheDataManager::instance()->addCacheData///< 添加配置信息
#define __CacheData CacheDataManager::instance()->cacheData///< 获取配置信息
#define __Remove CacheDataManager::instance()->remove///< 移除配置信息
#define __Groups CacheDataManager::instance()->groups///< 获取所有组
#define __BeginGroups CacheDataManager::instance()->begingroups///< 获取以str开始的所有组
#define __EndGroups CacheDataManager::instance()->endgroups///< 获取以str结尾的所有组
#define __Keys CacheDataManager::instance()->keys///< 获取组下的key
相关推荐
尘客-追梦2 小时前
Day 01:插件化之前,先看清 ABI 这堵墙
开发语言·c++·qt
小lu飞4 小时前
DeepSeek Flash 降价的技术账本:缓存友好型定价如何改写推理成本结构
缓存
golang学习记5 小时前
Go 1.27新特性: json/v2使用有趣指南
开发语言·golang·json
Quz5 小时前
QML SwipeView:实现一个简单的图片浏览器
qt
Quz5 小时前
QML SwipeView:标签导航 与 Loader 懒加载
qt
hweiyu006 小时前
Redis命令:APPEND
redis·缓存
敲代码的嘎仔7 小时前
从集群锁失效到异步领券:我用分布式锁 + Redisson + MQ 把领券接口 RT 从 200ms 压到 15ms
java·数据库·redis·分布式·缓存·ai·wpf
神仙别闹9 小时前
基于 QT(C++)开发的地铁换乘系统
数据库·c++·qt
MetaLite10 小时前
Spring Cache只留注解-MetaLite如何二开缓存运行时
java·spring·缓存