Asp.Net Core webapi+net6 使用资源筛选器(过滤器) 做缓存

  • Asp.Net Core webapi+net6 使用资源筛选器(过滤器) 做缓存已关闭评论
  • 92 次浏览
  • A+
所属分类:.NET技术
摘要

写一个特性类,用来做标记我这里使用了MemoryCache来做缓存,也可以使用字典来做,但一定要加上static,否则字典每一次请求都会new一个实例,缓存的东西就丢了

写一个特性类,用来做标记

[AttributeUsage(AttributeTargets.Method)] //只对方法有效 public class ResourceFilterAttribute : Attribute {  } 

我这里使用了MemoryCache来做缓存,也可以使用字典来做,但一定要加上static,否则字典每一次请求都会new一个实例,缓存的东西就丢了

private static Dictionary<string,object> caCheDic=new Dictionary<string, object>(); 

过滤器代码实现

public class ResourceFilter : IAsyncResourceFilter { private readonly IMemoryCache cache;  public ResourceFilter(IMemoryCache cache) { this.cache = cache; } public async Task OnResourceExecutionAsync(ResourceExecutingContext context, ResourceExecutionDelegate next) { //获取当前正在处理的控制器动作方法的相关信息,例如方法名、参数 var actionDescriptor = context.ActionDescriptor as ControllerActionDescriptor;  // 检查当前请求是否为 Controller Action if (actionDescriptor == null) { await next(); return; }  // 检查当前 Action 是否包含 ResourceFilterAttribute,如果没有则继续处理下一个中间件 if (!actionDescriptor.MethodInfo.GetCustomAttributes(typeof(ResourceFilterAttribute), true).Any()) { await next(); return; }  //把请求的ip和方法名当做缓存的key var cacheKey=context.HttpContext.Connection.RemoteIpAddress.ToString()+actionDescriptor.ActionName; //去缓存中找 如果有则直接返回 if (cache.TryGetValue(cacheKey, out IActionResult resultFromCache)) { context.Result= resultFromCache; return; }  // 执行下一个中间件并获取结果 var resultContext =await next();  // 如果结果是 IActionResult 类型,则将结果缓存起来 if (resultContext.Result is IActionResult actionResult) { //缓存时间 var cacheOptions = new MemoryCacheEntryOptions() .SetSlidingExpiration(TimeSpan.FromSeconds(10)); cache.Set(cacheKey, actionResult, cacheOptions); }  context.Result = resultContext.Result; } } 

在program类中要注入MemoryCache

builder.Services.AddMemoryCache(); 

还要进行配置我们刚才写的筛选器

builder.Services.AddControllers().AddMvcOptions(option => { option.Filters.Add(typeof(ResourceFilter)); }); 

在需要进行缓存的action头上加上ResourceFilter特性,表示这个action的返回结果要进行缓存

[Route("api/[controller]/[action]"), ApiController] public class TestController : ControllerBase { List<SysUser> sysUsers = new List<SysUser>() { new SysUser("admin","123"), new SysUser("admin2","123") }; [HttpGet, ResourceFilter] public List<SysUser> GetUsers() { return sysUsers; } } public record SysUser(string loginName,string loginPwd); 

进行测试,我这里直接就是截图的第二次请求,可以看到,请求去缓存里面读到了数据
Asp.Net Core webapi+net6 使用资源筛选器(过滤器) 做缓存

还有需要注意的是,尽量不要在缓存中存储IQuerytable和IEnumtable等具有延迟执行的类型或接口的数据,因为是延迟执行,IQuerytable和IEnumtable都是生成的sql语句,所以在使用ef时,这些数据还是会去进行数据库操作,这样我们的缓存也就没有意义了。