【后端】.NET Core API框架搭建(7) --配置使用Redis
目录
1.添加包
2. 连接配置
2.1.连接字符串
2.2.连接对象
3.仓储配置
3.1.仓储实现
3.2.仓储接口
4.获取配置和注册
4.1.添加配置获取方法
4.2.注册
5.简单使用案例
5.1.实现
5.2.接口
5.3.控制器
在 .NET Core 应用程序中使用 Redis 有许多显著的好处,Redis 是一种高性能的键值存储系统,通常被用作数据库、缓存和消息代理。增强的性能表现以及更高的灵活性和可靠性,适用于从简单的缓存方案到复杂的分布式应用架构。
1.添加包
添加 StackExchange.Redis 和 Microsoft.Extensions.Caching.StackExchangeRedis 包。
2. 连接配置
2.1.连接字符串
dbsettings.json文件添加 Redis连接配置
//Redis配置"RedisSettings": {"RedisConnStr": "ip地址:端口,password=密码,abortConnect=false"},
2.2.连接对象
namespace Frame3_DataRepository.RedisRepository
{public class RedisOptions{/// <summary>/// 连接地址/// </summary>public string RedisConnStr { get; set; }}
}
案例如下
3.仓储配置
3.1.仓储实现
为 Redis 添加仓储方便使用。
using Frame6_LibraryUtility;
using StackExchange.Redis;
using System.Text.Json;namespace Frame3_DataRepository.RedisRepository
{public class RedisRepository : BaseServiceSingleton, IRedisRepository{private readonly IConnectionMultiplexer _redis;/// <summary>/// /// </summary>/// <param name="redis"></param>public RedisRepository(IConnectionMultiplexer redis){_redis = redis;}/// <summary>/// 设置键值对/// </summary>public async Task<bool> SetAsync<T>(string key, T value, int dbNumber = 1, TimeSpan? expiry = null){var database = _redis.GetDatabase(dbNumber);var json = JsonSerializer.Serialize(value);return await database.StringSetAsync(key, json, expiry);}/// <summary>/// 获取值/// </summary>public async Task<T> GetAsync<T>(string key, int dbNumber = 1){var database = _redis.GetDatabase(dbNumber);var json = await database.StringGetAsync(key);return json.IsNullOrEmpty ? default : JsonSerializer.Deserialize<T>(json);}/// <summary>/// 删除键/// </summary>public async Task<bool> RemoveAsync(string key, int dbNumber = 1){var database = _redis.GetDatabase(dbNumber);return await database.KeyDeleteAsync(key);}/// <summary>/// 检查键是否存在/// </summary>public async Task<bool> ExistsAsync(string key, int dbNumber = 1){var database = _redis.GetDatabase(dbNumber);return await database.KeyExistsAsync(key);}/// <summary>/// 更新键值/// </summary>public async Task<bool> UpdateAsync<T>(string key, T value, int dbNumber = 1, TimeSpan? expiry = null){if (!await ExistsAsync(key, dbNumber))return false;return await SetAsync(key, value, dbNumber, expiry);}/// <summary>/// 搜索匹配的键/// </summary>public async Task<IEnumerable<string>> SearchKeysAsync(string pattern, int dbNumber = 1){var database = _redis.GetDatabase(dbNumber);var endpoints = _redis.GetEndPoints();var server = _redis.GetServer(endpoints.First());var keys = server.Keys(pattern: $"*{pattern}*");return keys.Select(k => k.ToString());}/// <summary>/// 按模式删除键/// </summary>public async Task<long> RemoveByPatternAsync(string pattern, int dbNumber = 1){var database = _redis.GetDatabase(dbNumber);var keys = await SearchKeysAsync(pattern, dbNumber);if (!keys.Any())return 0;return await database.KeyDeleteAsync(keys.Select(k => (RedisKey)k).ToArray());}/// <summary>/// 设置哈希字段值/// </summary>public async Task<bool> SetHashAsync<T>(string hashKey, string field, T value, int dbNumber = 1){var database = _redis.GetDatabase(dbNumber);var json = JsonSerializer.Serialize(value);return await database.HashSetAsync(hashKey, field, json);}/// <summary>/// 获取哈希字段值/// </summary>public async Task<T> GetHashAsync<T>(string hashKey, string field, int dbNumber = 1){var database = _redis.GetDatabase(dbNumber);var json = await database.HashGetAsync(hashKey, field);return json.IsNullOrEmpty ? default : JsonSerializer.Deserialize<T>(json);}/// <summary>/// 删除哈希字段/// </summary>public async Task<bool> RemoveHashAsync(string hashKey, string field, int dbNumber = 1){var database = _redis.GetDatabase(dbNumber);return await database.HashDeleteAsync(hashKey, field);}/// <summary>/// 获取所有哈希字段/// </summary>public async Task<Dictionary<string, T>> GetAllHashAsync<T>(string hashKey, int dbNumber = 1){var database = _redis.GetDatabase(dbNumber);var entries = await database.HashGetAllAsync(hashKey);return entries.ToDictionary(x => x.Name.ToString(),x => JsonSerializer.Deserialize<T>(x.Value));}/// <summary>/// 获取所有哈希字段 -- List返回/// </summary>public async Task<List<T>> GetAllListHashAsync<T>(string hashKey, int dbNumber = 1){var database = _redis.GetDatabase(dbNumber);var entries = await database.HashGetAllAsync(hashKey);var list = new List<T>();foreach (var item in entries){list.Add(JsonSerializer.Deserialize<T>(item.Value));}return list;}}
}
案例如下
3.2.仓储接口
namespace Frame3_DataRepository.RedisRepository
{public interface IRedisRepository{/// <summary>/// 设置键值对/// </summary>Task<bool> SetAsync<T>(string key, T value, int dbNumber, TimeSpan? expiry = null);/// <summary>/// 获取值/// </summary>Task<T> GetAsync<T>(string key, int dbNumber);/// <summary>/// 删除键/// </summary>Task<bool> RemoveAsync(string key, int dbNumber);/// <summary>/// 检查键是否存在/// </summary>Task<bool> ExistsAsync(string key, int dbNumber);/// <summary>/// 更新键值/// </summary>Task<bool> UpdateAsync<T>(string key, T value, int dbNumber, TimeSpan? expiry = null);/// <summary>/// 搜索匹配的键/// </summary>Task<IEnumerable<string>> SearchKeysAsync(string pattern, int dbNumber);/// <summary>/// 按模式删除键/// </summary>Task<long> RemoveByPatternAsync(string pattern, int dbNumber);/// <summary>/// 设置哈希字段值/// </summary>Task<bool> SetHashAsync<T>(string hashKey, string field, T value, int dbNumber);/// <summary>/// 获取哈希字段值/// </summary>Task<T> GetHashAsync<T>(string hashKey, string field, int dbNumber);/// <summary>/// 删除哈希字段/// </summary>Task<bool> RemoveHashAsync(string hashKey, string field, int dbNumber);/// <summary>/// 获取所有哈希字段/// </summary>Task<Dictionary<string, T>> GetAllHashAsync<T>(string hashKey, int dbNumber);/// <summary>/// 获取所有哈希字段 -- List返回/// </summary>Task<List<T>> GetAllListHashAsync<T>(string hashKey, int dbNumber);}
}
案例如下
4.获取配置和注册
获取连接字符串、注册Redis实例和仓储
4.1.添加配置获取方法
using Microsoft.Extensions.Configuration;namespace Frame4_LibraryCore.BaseConfig
{/// <summary>/// 全局配置/// </summary>public static class Config{/// <summary>/// 从指定的 JSON 配置文件中读取配置,并反序列化为指定类型/// </summary>/// <typeparam name="T">目标配置类型(如 RedisSettings、DatabaseSettings 等)</typeparam>/// <param name="fileName">JSON 配置文件名(如 "appsettings.json")</param>/// <param name="sessions">配置节点名称(如 "RedisSettings")</param>/// <returns>返回绑定后的强类型配置对象</returns>public static T GetSetting<T>(string fileName, string sessions){//创建 ConfigurationBuilder 实例,用于构建配置var builder = new ConfigurationBuilder()//设置配置文件的基础路径为当前程序运行目录.SetBasePath(Directory.GetCurrentDirectory())//添加 JSON 文件作为配置源://- fileName: 指定要加载的 JSON 文件//- optional: false 表示文件必须存在,否则抛出异常//- reloadOnChange: true 表示文件修改时自动重新加载.AddJsonFile(fileName, optional: false, reloadOnChange: true);//构建配置对象(IConfigurationRoot)IConfigurationRoot config = builder.Build();//获取指定配置节点(sessions),并将其反序列化为类型 Tvar conn = config.GetSection(sessions).Get<T>();//返回反序列化后的配置对象return conn;}}
}
案例如下
4.2.注册
添加注册方法方便程序注册
using Frame4_LibraryCore.BaseConfig;
using Microsoft.Extensions.DependencyInjection;
using StackExchange.Redis;namespace Frame3_DataRepository.RedisRepository
{/// <summary>/// Redis扩展方法静态类,用于配置Redis相关服务/// </summary>public static class RedisExtension{/// <summary>/// 扩展方法:向IServiceCollection添加Redis仓储相关服务/// </summary>/// <param name="services">服务集合</param>/// <returns>配置后的服务集合</returns>public static IServiceCollection AddRedisRepository(this IServiceCollection services){// 从配置文件"dbsettings.json"的"RedisSettings"节点读取Redis配置var redisConn = Config.GetSetting<RedisOptions>("dbsettings.json", "RedisSettings");// 添加StackExchange.Redis缓存服务(基于IDistributedCache接口)services.AddStackExchangeRedisCache(options =>{// 配置Redis连接字符串(从redisConn对象获取)options.Configuration = redisConn.RedisConnStr;// 设置实例名称前缀(用于区分不同应用的缓存键)// 例如:设置"MyApp_"前缀后,实际缓存键会变成"MyApp_UserCache"options.InstanceName = "MyApp_"; // 所有缓存键自动添加此前缀});// 直接注册ConnectionMultiplexer为单例服务(Redis连接复用)// ConnectionMultiplexer是线程安全的,适合单例模式services.AddSingleton<IConnectionMultiplexer>(_ =>ConnectionMultiplexer.Connect(redisConn.RedisConnStr));// 注册Redis仓储实现(IRedisRepository接口对应RedisRepository实现类)// 使用单例模式注册,因为RedisRepository内部使用线程安全的ConnectionMultiplexerservices.AddSingleton<IRedisRepository, RedisRepository>();// 返回配置好的服务集合以支持链式调用return services;}}
}
案例如下
新增好注册方法后即可在 Program 或 Startup 中注册。
//注册Redis服务builder.Services.AddRedisRepository();
案例如下
5.简单使用案例
下面是 实现、接口和控制器的使用案例
5.1.实现
using Frame1_Service.IService.Product;
using Frame2_DataModel.MongoEntity.Product;
using Frame3_DataRepository.RedisRepository;
using Frame6_LibraryUtility;namespace Frame1_Service.Service.Product
{public class RedisSvr : BaseService, IRedisSvr{/// <summary>/// RedisKey/// </summary>private const string ProductsKey = "products";/// <summary>/// Redis缓存/// </summary>private readonly IRedisRepository _redisRepository;/// <summary>/// redis数据库编号/// </summary>private int dBNumber = 1;public RedisSvr(IRedisRepository redisRepository){_redisRepository = redisRepository;}/// <summary>/// 添加数据-键值对 30后自动删除,可用于分布式锁/// </summary>/// <returns></returns>public async Task<string> CacheCatalogItemsAsync(){var Gid = Guid.NewGuid().ToString();// 设置缓存,过期时间30秒var Ref = await _redisRepository.SetAsync(ProductsKey, Gid, dBNumber, TimeSpan.FromSeconds(30));if (!Ref){return null;}return Gid;}/// <summary>/// 查询数据 获取键值对/// </summary>/// <returns></returns>public async Task<string> GetRedisByIdAsync(){//redis测试查询setvar list = await _redisRepository.GetAsync<string>(ProductsKey, dBNumber);return list;}/// <summary>/// 添加数据/// </summary>/// <param name="model"></param>/// <returns></returns>public async Task<bool> IndertAsync(ProductEntity model){var iRet = false;iRet = await _redisRepository.SetHashAsync(ProductsKey, model.Id, model, 2);return iRet;}/// <summary>/// 查询数据/// </summary>/// <param name="key"></param>/// <returns></returns>public async Task<ProductEntity> GetRedisAsync(string key){//redis测试查询setvar list = await _redisRepository.GetHashAsync<ProductEntity>(ProductsKey, key, 2);return list;}/// <summary>/// 查询所有数据/// </summary>/// <returns></returns>public async Task<dynamic> GetAllRedisAsync(){//redis测试查询setvar list = await _redisRepository.GetAllHashAsync<ProductEntity>(ProductsKey, 2);return list;}/// <summary>/// 查询所有数据集合显示/// </summary>/// <returns></returns>public async Task<dynamic> GetAllListRedisAsync(){//redis测试查询setvar list = await _redisRepository.GetAllListHashAsync<ProductEntity>(ProductsKey, 2);return list;}/// <summary>/// 添加集合数据/// </summary>/// <param name="model"></param>/// <returns></returns>public async Task<bool> IndertGatherAsync(List<ProductEntity> model){var iRet = false;iRet = await _redisRepository.SetHashAsync(ProductsKey, Guid.NewGuid().ToString(), model, 3);return iRet;}/// <summary>/// 查询所有集合数据/// </summary>/// <returns></returns>public async Task<dynamic> GetGatherAllRedisAsync(){//redis测试查询setvar list = await _redisRepository.GetAllHashAsync<List<ProductEntity>>(ProductsKey, 3);return list;}}
}
案例如下
5.2.接口
using Frame2_DataModel.MongoEntity.Product;namespace Frame1_Service.IService.Product
{public interface IRedisSvr{Task<string> CacheCatalogItemsAsync();/// <summary>/// 查询数据 获取键值对/// </summary>/// <param name="model"></param>/// <returns></returns>Task<string> GetRedisByIdAsync();/// <summary>/// 添加数据/// </summary>/// <param name="model"></param>/// <returns></returns>Task<bool> IndertAsync(ProductEntity model);/// <summary>/// 查询数据/// </summary>/// <param name="model"></param>/// <returns></returns>Task<ProductEntity> GetRedisAsync(string key);/// <summary>/// 查询所有数据/// </summary>/// <param name="model"></param>/// <returns></returns>Task<dynamic> GetAllRedisAsync();/// <summary>/// 查询所有数据集合显示/// </summary>/// <returns></returns>Task<dynamic> GetAllListRedisAsync();/// <summary>/// 添加集合数据/// </summary>/// <param name="model"></param>/// <returns></returns>Task<bool> IndertGatherAsync(List<ProductEntity> model);/// <summary>/// 查询所有集合数据/// </summary>/// <returns></returns>Task<dynamic> GetGatherAllRedisAsync();}
}
案例如下
5.3.控制器
using Frame1_Service.IService.Product;
using Frame2_DataModel.MongoEntity.Product;
using Frame3_DataRepository.RedisRepository;
using Frame4_LibraryCore.BaseConfig;
using Microsoft.AspNetCore.DataProtection.KeyManagement;
using Microsoft.AspNetCore.Mvc;namespace DemoAPI.Controllers
{/// <summary>/// Redis测试控制器/// </summary>//[Authorize]// 保护整个控制器[Route("api/[controller]/[action]")]//标记路由地址规格[ApiController] // 标记该类为 API 控制器,启用一些默认的行为,如模型绑定、输入验证等[ApiExplorerSettings(GroupName = nameof(ApiVersionInfo.V1))]//设置控制器的API版本public class RedisTestController : BaseController{private readonly IRedisSvr _iRedisSvr;/// <summary>/// 注入/// </summary>/// <param name="iRedisSvr"></param>public RedisTestController(IRedisSvr iRedisSvr){_iRedisSvr = iRedisSvr;}/// <summary>/// 添加数据-键值对 30后自动删除,可用于分布式锁/// </summary>/// <returns></returns>[HttpGet]public async Task<string> CacheCatalogItemsAsync() => await _iRedisSvr.CacheCatalogItemsAsync();/// <summary>/// 查询数据 获取键值对/// </summary>/// <returns></returns>[HttpGet]public async Task<string> GetRedisByIdAsync() => await _iRedisSvr.GetRedisByIdAsync();/// <summary>/// 添加数据/// </summary>/// <param name="model"></param>/// <returns></returns>[HttpPost]public async Task<bool> IndertAsync(ProductEntity model) => await _iRedisSvr.IndertAsync(model);/// <summary>/// 查询数据/// </summary>/// <param name="key"></param>/// <returns></returns>[HttpGet]public async Task<ProductEntity> GetRedisAsync(string key) => await _iRedisSvr.GetRedisAsync(key);/// <summary>/// 查询所有数据/// </summary>/// <returns></returns>[HttpGet]public async Task<dynamic> GetAllRedisAsync() => await _iRedisSvr.GetAllRedisAsync();/// <summary>/// 查询所有数据集合显示/// </summary>/// <returns></returns>[HttpGet]public async Task<dynamic> GetAllListRedisAsync() => await _iRedisSvr.GetAllListRedisAsync();/// <summary>/// 添加集合数据/// </summary>/// <param name="model"></param>/// <returns></returns>[HttpPost]public async Task<bool> IndertGatherAsync(List<ProductEntity> model) => await _iRedisSvr.IndertGatherAsync(model);/// <summary>/// 查询所有集合数据/// </summary>/// <returns></returns>[HttpGet]public async Task<dynamic> GetGatherAllRedisAsync() => await _iRedisSvr.GetGatherAllRedisAsync();}
}
案例如下