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


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

    [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 sysUsers = new List()
    {
    new SysUser("admin","123"),
    new SysUser("admin2","123")
    };
    [HttpGet, ResourceFilter]
    public List GetUsers() { return sysUsers; }
    }
    public record SysUser(string loginName,string loginPwd);
    

    进行测试,我这里直接就是截图的第二次请求,可以看到,请求去缓存里面读到了数据
    image

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

  • 相关阅读:
    差分约束——区间
    云计算与大数据第15章 分布式大数据处理平台Hadoop习题带答案
    【Python】进阶学习:基于Matplotlib--使用plt.savefig()实现图形文件的保存
    计算机毕业设计(附源码)python智慧灭火器管理系统
    金仓数据库 KingbaseES 插件参考手册 H
    MAC版InDesign 2022 17.4(ID2022)已发布,原生支持Intel和M1/M2三系统,速度提升80%
    记我第一次做线下技术分享的那些事
    11.11 - 每日一题 - 408
    CVE-2022-26134 Confluence OGNL表达式注入命令执行漏洞复现
    html和css中的图片加载与渲染规则是什么样的?
  • 原文地址:https://www.cnblogs.com/cyfj/p/17815126.html