🚀 feat(新增): 实现RedisCache注解
This commit is contained in:
parent
faf760029e
commit
a609bb1dd4
|
@ -0,0 +1,11 @@
|
||||||
|
namespace Bunny.Common.Attribute;
|
||||||
|
|
||||||
|
[AttributeUsage(AttributeTargets.Method)]
|
||||||
|
public class CacheableAttribute(string key, string durationString) : System.Attribute
|
||||||
|
{
|
||||||
|
// 构造函数接收一个表示时间的字符串参数
|
||||||
|
// 将字符串转换为TimeSpan
|
||||||
|
|
||||||
|
public string? Key { get; set; } = key;
|
||||||
|
public TimeSpan TimeDuration { get; set; } = TimeSpan.Parse(durationString);
|
||||||
|
}
|
|
@ -1,6 +1,4 @@
|
||||||
namespace Bunny.Common.Attribute;
|
namespace Bunny.Common.Attribute;
|
||||||
|
|
||||||
[AttributeUsage(AttributeTargets.Method)]
|
[AttributeUsage(AttributeTargets.Method)]
|
||||||
public class TransactionAttribute : System.Attribute
|
public class TransactionAttribute : System.Attribute;
|
||||||
{
|
|
||||||
}
|
|
|
@ -7,6 +7,7 @@
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
<PackageReference Include="Castle.Core" Version="5.1.1"/>
|
||||||
<PackageReference Include="log4net" Version="2.0.17"/>
|
<PackageReference Include="log4net" Version="2.0.17"/>
|
||||||
<PackageReference Include="Microsoft.AspNetCore" Version="2.2.0"/>
|
<PackageReference Include="Microsoft.AspNetCore" Version="2.2.0"/>
|
||||||
<PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="8.0.6"/>
|
<PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="8.0.6"/>
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
using Bunny.Dao.Entity;
|
using Bunny.Dao.Entity;
|
||||||
using Bunny.Dao.Entity.System;
|
using Bunny.Dao.Entity.System;
|
||||||
|
using Bunny.Dao.Entity.System.Dept;
|
||||||
using Bunny.Dao.Entity.System.Menu;
|
using Bunny.Dao.Entity.System.Menu;
|
||||||
using Bunny.Dao.Entity.System.User;
|
using Bunny.Dao.Entity.System.User;
|
||||||
using log4net;
|
using log4net;
|
||||||
|
@ -30,6 +31,7 @@ public class EfCoreContext : DbContext
|
||||||
private string DbPath { get; }
|
private string DbPath { get; }
|
||||||
public DbSet<Icons> Icons { get; set; }
|
public DbSet<Icons> Icons { get; set; }
|
||||||
public DbSet<Dept> Dept { get; set; }
|
public DbSet<Dept> Dept { get; set; }
|
||||||
|
public DbSet<DeptUsers> DeptUsers { get; set; }
|
||||||
public DbSet<Users> Users { get; set; }
|
public DbSet<Users> Users { get; set; }
|
||||||
public DbSet<Roles> Roles { get; set; }
|
public DbSet<Roles> Roles { get; set; }
|
||||||
public DbSet<Permissions> Permissions { get; set; }
|
public DbSet<Permissions> Permissions { get; set; }
|
||||||
|
@ -44,7 +46,6 @@ public class EfCoreContext : DbContext
|
||||||
/// </summary>
|
/// </summary>
|
||||||
protected override void OnConfiguring(DbContextOptionsBuilder options)
|
protected override void OnConfiguring(DbContextOptionsBuilder options)
|
||||||
{
|
{
|
||||||
Log.Info("EfCoreContext 数据库连接...");
|
|
||||||
options.UseSqlServer(DbPath);
|
options.UseSqlServer(DbPath);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -12,31 +12,28 @@ public static class RedisContext
|
||||||
|
|
||||||
public static void AddRedisContext(this WebApplicationBuilder builder)
|
public static void AddRedisContext(this WebApplicationBuilder builder)
|
||||||
{
|
{
|
||||||
Task.Run(() =>
|
// 获取端口等配置信息
|
||||||
|
var host = AppSettings.GetConfig("Redis:Host");
|
||||||
|
var port = Convert.ToInt32(AppSettings.GetConfig("Redis:Port"));
|
||||||
|
var defaultDb = Convert.ToInt32(AppSettings.GetConfig("Redis:DefaultDB"));
|
||||||
|
var password = AppSettings.Get<string>("Redis:Password");
|
||||||
|
var timeout = Convert.ToInt32(AppSettings.GetConfig("Redis:AsyncTimeout"));
|
||||||
|
|
||||||
|
// 添加连接地址
|
||||||
|
EndPointCollection.Add(host, port);
|
||||||
|
|
||||||
|
// 初始化连接对象
|
||||||
|
var connect = ConnectionMultiplexer.Connect(new ConfigurationOptions
|
||||||
{
|
{
|
||||||
// 获取端口等配置信息
|
EndPoints = EndPointCollection,
|
||||||
var host = AppSettings.GetConfig("Redis:Host");
|
Password = password,
|
||||||
var port = Convert.ToInt32(AppSettings.GetConfig("Redis:Port"));
|
DefaultDatabase = defaultDb,
|
||||||
var defaultDb = Convert.ToInt32(AppSettings.GetConfig("Redis:DefaultDB"));
|
AsyncTimeout = timeout
|
||||||
var password = AppSettings.Get<string>("Redis:Password");
|
|
||||||
var timeout = Convert.ToInt32(AppSettings.GetConfig("Redis:AsyncTimeout"));
|
|
||||||
|
|
||||||
// 添加连接地址
|
|
||||||
EndPointCollection.Add(host, port);
|
|
||||||
|
|
||||||
// 初始化连接对象
|
|
||||||
var connect = ConnectionMultiplexer.Connect(new ConfigurationOptions
|
|
||||||
{
|
|
||||||
EndPoints = EndPointCollection,
|
|
||||||
Password = password,
|
|
||||||
DefaultDatabase = defaultDb,
|
|
||||||
AsyncTimeout = timeout
|
|
||||||
});
|
|
||||||
|
|
||||||
// 创建连接对象
|
|
||||||
RedisDatabase = connect.GetDatabase();
|
|
||||||
|
|
||||||
Log.Info("Redis 初始化...");
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// 创建连接对象
|
||||||
|
RedisDatabase = connect.GetDatabase();
|
||||||
|
|
||||||
|
Log.Info("Redis 初始化...");
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -0,0 +1,73 @@
|
||||||
|
using System.Reflection;
|
||||||
|
using Bunny.Common.Attribute;
|
||||||
|
using Bunny.Common.Context.Middleware;
|
||||||
|
using Bunny.Dao.Common.Constant;
|
||||||
|
using Microsoft.AspNetCore.Mvc;
|
||||||
|
using Microsoft.AspNetCore.Mvc.Controllers;
|
||||||
|
using Microsoft.AspNetCore.Mvc.Filters;
|
||||||
|
using Newtonsoft.Json;
|
||||||
|
using Newtonsoft.Json.Serialization;
|
||||||
|
using IDatabase = StackExchange.Redis.IDatabase;
|
||||||
|
|
||||||
|
namespace Bunny.Common.Filter;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Redis缓存注解
|
||||||
|
/// </summary>
|
||||||
|
public class CacheIiAsyncActionFilter : IAsyncActionFilter
|
||||||
|
{
|
||||||
|
private readonly IDatabase _redisDatabase = RedisContext.RedisDatabase!;
|
||||||
|
|
||||||
|
public async Task OnActionExecutionAsync(ActionExecutingContext context, ActionExecutionDelegate next)
|
||||||
|
{
|
||||||
|
var actionDesc = context.ActionDescriptor as ControllerActionDescriptor;
|
||||||
|
var hasCacheableAttribute = actionDesc?.MethodInfo.IsDefined(typeof(CacheableAttribute), false) ?? false;
|
||||||
|
|
||||||
|
// 如果没有加注解直接返回
|
||||||
|
if (!hasCacheableAttribute)
|
||||||
|
{
|
||||||
|
await next();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取注解中的值
|
||||||
|
var cacheableAttribute = actionDesc?.MethodInfo.GetCustomAttribute<CacheableAttribute>();
|
||||||
|
|
||||||
|
// 注解为空
|
||||||
|
if (cacheableAttribute?.Key == null)
|
||||||
|
{
|
||||||
|
await next();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 缓存的key
|
||||||
|
var cacheKey = cacheableAttribute.Key;
|
||||||
|
// 缓存时间
|
||||||
|
var duration = cacheableAttribute.TimeDuration;
|
||||||
|
|
||||||
|
// 缓存数据
|
||||||
|
var cachedData = _redisDatabase.StringGet(cacheKey);
|
||||||
|
|
||||||
|
// 如果注解中有值将值赋值给返回结果
|
||||||
|
if (!cachedData.IsNullOrEmpty)
|
||||||
|
{
|
||||||
|
context.Result = new ContentResult
|
||||||
|
{
|
||||||
|
Content = cachedData.ToString(),
|
||||||
|
ContentType = "application/json"
|
||||||
|
};
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 如果注解中没有值,赋值内容
|
||||||
|
var result = (ObjectResult)next().GetAwaiter().GetResult().Result!;
|
||||||
|
var jsonSettings = new JsonSerializerSettings
|
||||||
|
{
|
||||||
|
DateFormatString = LocalDateTimeConstant.DefaultDateTimeSecondFormat,
|
||||||
|
ContractResolver = new CamelCasePropertyNamesContractResolver()
|
||||||
|
};
|
||||||
|
// 现在你可以访问 result.Data
|
||||||
|
var json = JsonConvert.SerializeObject(result.Value, jsonSettings);
|
||||||
|
_redisDatabase.StringSet(cacheKey, json, duration);
|
||||||
|
}
|
||||||
|
}
|
|
@ -2,7 +2,7 @@
|
||||||
using System.ComponentModel.DataAnnotations.Schema;
|
using System.ComponentModel.DataAnnotations.Schema;
|
||||||
using Microsoft.EntityFrameworkCore;
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
|
||||||
namespace Bunny.Dao.Entity.System;
|
namespace Bunny.Dao.Entity.System.Dept;
|
||||||
|
|
||||||
[Comment("系统部门表")]
|
[Comment("系统部门表")]
|
||||||
[Table("System_Dept")]
|
[Table("System_Dept")]
|
|
@ -0,0 +1,12 @@
|
||||||
|
using System.ComponentModel.DataAnnotations.Schema;
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
|
||||||
|
namespace Bunny.Dao.Entity.System.Dept;
|
||||||
|
|
||||||
|
[Comment("部门和用户关系表")]
|
||||||
|
[Table("System_DeptUsers")]
|
||||||
|
public class DeptUsers : BaseEntity
|
||||||
|
{
|
||||||
|
[Comment("部门id")] public Guid DeptId { get; init; }
|
||||||
|
[Comment("用户id")] public Guid UserId { get; init; }
|
||||||
|
}
|
|
@ -61,7 +61,6 @@ public class UserService : IUserService
|
||||||
/// 批量添加数据
|
/// 批量添加数据
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="url"></param>
|
/// <param name="url"></param>
|
||||||
[Transaction]
|
|
||||||
public void AddBatchBlogs(string url)
|
public void AddBatchBlogs(string url)
|
||||||
{
|
{
|
||||||
var list = new List<Users>();
|
var list = new List<Users>();
|
||||||
|
@ -119,6 +118,7 @@ public class UserService : IUserService
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="page"></param>
|
/// <param name="page"></param>
|
||||||
/// <param name="limit"></param>
|
/// <param name="limit"></param>
|
||||||
|
[Cacheable("UserService::Get", "00:00:59")]
|
||||||
public PageResult<Users> QueryPage(int page, int limit)
|
public PageResult<Users> QueryPage(int page, int limit)
|
||||||
{
|
{
|
||||||
var items = DbContext.Users.Take(limit).Skip(page).ToList();
|
var items = DbContext.Users.Take(limit).Skip(page).ToList();
|
||||||
|
|
|
@ -19,9 +19,27 @@ public static class AddAutofacConfig
|
||||||
.Where(t => controllerBaseType.IsAssignableFrom(t) && t != controllerBaseType)
|
.Where(t => controllerBaseType.IsAssignableFrom(t) && t != controllerBaseType)
|
||||||
.PropertiesAutowired(); //支持属性注入
|
.PropertiesAutowired(); //支持属性注入
|
||||||
|
|
||||||
// 注入EfCore上下文对象
|
// 系统相关注入
|
||||||
builder.RegisterType<EfCoreContext>();
|
SystemRegisterType(builder);
|
||||||
|
// 服务相关注入
|
||||||
|
ServiceRegisterType(builder);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 系统相关注入
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="builder">ContainerBuilder</param>
|
||||||
|
private static void SystemRegisterType(ContainerBuilder builder)
|
||||||
|
{
|
||||||
|
builder.RegisterType<EfCoreContext>();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 服务相关注入
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="builder">ContainerBuilder</param>
|
||||||
|
private static void ServiceRegisterType(ContainerBuilder builder)
|
||||||
|
{
|
||||||
// 注入Service服务
|
// 注入Service服务
|
||||||
builder.RegisterType<BaseService>().As<IBaseService>();
|
builder.RegisterType<BaseService>().As<IBaseService>();
|
||||||
builder.RegisterType<UserService>().As<IUserService>();
|
builder.RegisterType<UserService>().As<IUserService>();
|
||||||
|
|
|
@ -20,6 +20,8 @@ public class BaseConfig(WebApplicationBuilder builder)
|
||||||
|
|
||||||
// 配置日志相关
|
// 配置日志相关
|
||||||
builder.Logging.AddLog4Net("Configuration/log4net.config");
|
builder.Logging.AddLog4Net("Configuration/log4net.config");
|
||||||
|
// 添加 ASP.NET 自带缓存
|
||||||
|
builder.Services.AddMemoryCache();
|
||||||
// 自定义时间格式
|
// 自定义时间格式
|
||||||
builder.Services.AddControllers().AddJsonOptions(options =>
|
builder.Services.AddControllers().AddJsonOptions(options =>
|
||||||
options.JsonSerializerOptions.Converters.Add(new JsonDateTimeConverter()));
|
options.JsonSerializerOptions.Converters.Add(new JsonDateTimeConverter()));
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
using Bunny.Common.Attribute;
|
using Bunny.Common.Filter;
|
||||||
using Bunny.Common.Filter;
|
|
||||||
using Bunny.Service.Job.JobService;
|
using Bunny.Service.Job.JobService;
|
||||||
using Lazy.Captcha.Core;
|
using Lazy.Captcha.Core;
|
||||||
using Lazy.Captcha.Core.Generator;
|
using Lazy.Captcha.Core.Generator;
|
||||||
|
@ -34,6 +33,7 @@ public static class ServiceRegistration
|
||||||
option.Filters.Add<ValidateModelStateAttribute>();
|
option.Filters.Add<ValidateModelStateAttribute>();
|
||||||
option.Filters.Add<TransactionIAsyncActionFilter>();
|
option.Filters.Add<TransactionIAsyncActionFilter>();
|
||||||
option.Filters.Add<AuthorizationFilter>();
|
option.Filters.Add<AuthorizationFilter>();
|
||||||
|
option.Filters.Add(typeof(CacheIiAsyncActionFilter));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
using Bunny.Dao.Common.Result;
|
using Bunny.Common.Attribute;
|
||||||
|
using Bunny.Dao.Common.Result;
|
||||||
using Bunny.Dao.Dto.System;
|
using Bunny.Dao.Dto.System;
|
||||||
using Bunny.Dao.Entity.System.User;
|
using Bunny.Dao.Entity.System.User;
|
||||||
using Bunny.Service.IService;
|
using Bunny.Service.IService;
|
||||||
|
@ -32,6 +33,7 @@ public class BlogController : ControllerBase
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
[HttpGet]
|
[HttpGet]
|
||||||
|
[Cacheable("QueryBlog", "00:00:59")]
|
||||||
public Result<List<Users>> QueryBlog()
|
public Result<List<Users>> QueryBlog()
|
||||||
{
|
{
|
||||||
var vo = UserService.QueryBlog();
|
var vo = UserService.QueryBlog();
|
||||||
|
|
|
@ -16,9 +16,9 @@
|
||||||
"Audience": "Audience"
|
"Audience": "Audience"
|
||||||
},
|
},
|
||||||
"Redis": {
|
"Redis": {
|
||||||
"Host": "47.120.65.66",
|
"Host": "192.168.3.98",
|
||||||
"Port": "6379",
|
"Port": "6379",
|
||||||
"Password": "02120212",
|
"Password": "123456",
|
||||||
"DefaultDB": 6,
|
"DefaultDB": 6,
|
||||||
"AsyncTimeout": 300
|
"AsyncTimeout": 300
|
||||||
},
|
},
|
||||||
|
|
|
@ -16,9 +16,9 @@
|
||||||
"Audience": "Audience"
|
"Audience": "Audience"
|
||||||
},
|
},
|
||||||
"Redis": {
|
"Redis": {
|
||||||
"Host": "47.120.65.66",
|
"Host": "192.168.3.98",
|
||||||
"Port": "6379",
|
"Port": "6379",
|
||||||
"Password": "02120212",
|
"Password": "123456",
|
||||||
"DefaultDB": 6,
|
"DefaultDB": 6,
|
||||||
"AsyncTimeout": 300
|
"AsyncTimeout": 300
|
||||||
},
|
},
|
||||||
|
|
Loading…
Reference in New Issue