RuoYI框架.net版本实现Redis数据隔离

效果图:实现两个name键同时存在,互不干扰。

在AppSetting中开启redis服务,在program.cs中会看到RedisServer.Initalize();但是此时并不能用,因为这个Initalize方法只是获取了cache和session,我们要加 RedisHelper.Initialization(Cache);实现真正的初始化实例。此时可以使用redis进行set get操作。但是还没有实现我们最终的目标。下一步就是做第二个实例。

在Common下创建UserMark.cs文件。

复制代码
using System;
using ZR.Common.Cache;

public  class UserMark { }
public  class UserRedisHelper : RedisHelper<UserMark>
{
    public static void BindRedis()
    {
        if (RedisServer.Cache == null)
            throw new Exception("initalize first");
        Initialization(RedisServer.UserCache);
}
}

可能要问为什么要这么写,继续看别人封装的Redis工具类,你可以看到在Controller里面可以直接使用RedisHelper进行操作。

这是为什么呢?你可以看到RedisHelper继承了RedisHelper,并传入了RedisHelper,继续点父类的RedisHelper

可以看到父类要求的参数是TMark,这是个什么东西呢?名为"泛型类",这就来到关键的地方了,怎么能实现数据隔离,同时存在相同的键,就是在这里,TMark是一个类型标记,主要用途是,区分不同的redis的使用场景,也就是我们的UserCache和Cache。

下面解释为什么可以直接在Controller里使用RedisHelper.Set("UserId", userId);

复制代码
// 1. 泛型父类(抽象,需指定 TMark)
public abstract class RedisHelper<TMark> 
{
    public static void Initialization(CSRedisClient csredis); // 父类静态初始化方法
    public static bool Set(string key, object value, ...); // 父类静态 Set 方法(核心)
}

// 2. 你的非泛型子类(继承父类,指定 TMark=RedisHelper)
public abstract class RedisHelper : RedisHelper<RedisHelper> 
{
    // 无额外代码,直接继承父类所有静态方法
}

public abstract class RedisHelper : RedisHelper<RedisHelper>是一个非泛型子类,他继承自泛型父类RedisHelper<TMark>并给父类的 TMark 泛型参数传了 "自身类型 RedisHelper" 作为标记。非泛型子类的核心作用:"消除泛型参数", 原本使用父类要写 RedisHelper<SomeMark>.Set(...),现在通过非泛型子类 RedisHelper,可以直接写 RedisHelper.Set(...),简化调用语法。仔细去看父类的工具类,public static静态方法。静态方法的特性就是,无需实例化,子类自动继承。第二个原因就是,RedisHelper.Initialization ,已初始化Instance。这个instance工具类很多都能用到。

对此已解释上面的疑惑。开始实现我们的代码

在上面的RedisServer中把注释打开。用于初始化

看Appsetting里的prefix= 字段,两者会配置不同的键前缀(Prefix), 为了区分不同业务场景的 Redis 操作 ,核心目的是避免键冲突、隔离数据、方便管理。

准备工作全都做好,下面开始验证,在两个接口里分别set一个键相同的缓存

复制代码
 #region
 [HttpGet("testRedisSet")]
 [Log(Title = "TestMessageLost", BusinessType = BusinessType.EXPORT, IsSaveResponseData = false)]
 [AllowAnonymous]
 public  IActionResult TestRedisSet(int userId)
 {
     var response = RedisHelper.Set("UserId", userId);
     RedisHelper.Set("name", "Lisa");
     return SUCCESS(response);
 }
 #endregion

 #region
 [HttpGet("testRedisGet")]
 [Log(Title = "TestMessageLost", BusinessType = BusinessType.EXPORT, IsSaveResponseData = false)]
 [AllowAnonymous]
 public IActionResult TestRedisGet(int userId)
 {
     var userRedis2 = UserRedisHelper.Set("name", "Pony2");
     var getUser2 = UserRedisHelper.Get("name");
     return SUCCESS($"{userRedis2}+{getUser2}");
 }
 #endregion

成功!!!

相关推荐
云烟成雨TD1 小时前
Spring AI Alibaba 1.x 系列【69】Token 用量统计
java·人工智能·spring
JAVA9651 小时前
JAVA面试-并发篇 03-使用synchronized doublecheck实现单例有什么坑
java·单例模式·面试
在繁华处1 小时前
Java从零到熟练(四):面向对象基础
java·开发语言
Unbelievabletobe1 小时前
解决了股票api接口盘后数据更新慢的问题
大数据·开发语言·python
不会C语言的男孩2 小时前
C++ Primer 第2章:变量和基本类型
开发语言·c++
小江的记录本3 小时前
【JVM虚拟机】堆内存分代模型:年轻代(Eden+Survivor)、老年代、元空间Metaspace(附《思维导图》+《面试高频考点清单》)
java·前端·jvm·后端·python·spring·面试
在繁华处3 小时前
Java从零到熟练(三):流程控制
java·开发语言·python
唐青枫3 小时前
Java Optional 实战指南:优雅处理空值与链式转换
java
一起学开源3 小时前
一文读懂 ReAct 范式:让 AI Agent 真正学会“思考+行动“
java·javascript·react.js·ecmascript·react·alibaba·智能体开发
云泽8084 小时前
C++ 可调用对象通关指南:深度解析 Lambda 表达式、function 包装器与 bind 绑定器
开发语言·c++·算法