翼度科技»论坛 编程开发 .net 查看内容

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

9

主题

9

帖子

27

积分

新手上路

Rank: 1

积分
27
写一个特性类,用来做标记
  1. [AttributeUsage(AttributeTargets.Method)] //只对方法有效
  2. public class ResourceFilterAttribute : Attribute
  3. {
  4. }
复制代码
我这里使用了MemoryCache来做缓存,也可以使用字典来做,但一定要加上static,否则字典每一次请求都会new一个实例,缓存的东西就丢了
  1. private static Dictionary<string,object> caCheDic=new Dictionary<string, object>();
复制代码
过滤器代码实现
  1. public class ResourceFilter : IAsyncResourceFilter
  2. {
  3. private readonly IMemoryCache cache;
  4. public ResourceFilter(IMemoryCache cache)
  5. {
  6. this.cache = cache;
  7. }
  8. public async Task OnResourceExecutionAsync(ResourceExecutingContext context, ResourceExecutionDelegate next)
  9. {
  10. //获取当前正在处理的控制器动作方法的相关信息,例如方法名、参数
  11. var actionDescriptor = context.ActionDescriptor as ControllerActionDescriptor;
  12. // 检查当前请求是否为 Controller Action
  13. if (actionDescriptor == null)
  14. {
  15. await next();
  16. return;
  17. }
  18. // 检查当前 Action 是否包含 ResourceFilterAttribute,如果没有则继续处理下一个中间件
  19. if (!actionDescriptor.MethodInfo.GetCustomAttributes(typeof(ResourceFilterAttribute), true).Any())
  20. {
  21. await next();
  22. return;
  23. }
  24. //把请求的ip和方法名当做缓存的key
  25. var cacheKey=context.HttpContext.Connection.RemoteIpAddress.ToString()+actionDescriptor.ActionName;
  26. //去缓存中找 如果有则直接返回
  27. if (cache.TryGetValue(cacheKey, out IActionResult resultFromCache))
  28. {
  29. context.Result= resultFromCache;
  30. return;
  31. }
  32. // 执行下一个中间件并获取结果
  33. var resultContext =await next();
  34. // 如果结果是 IActionResult 类型,则将结果缓存起来
  35. if (resultContext.Result is IActionResult actionResult)
  36. {
  37. //缓存时间
  38. var cacheOptions = new MemoryCacheEntryOptions()
  39. .SetSlidingExpiration(TimeSpan.FromSeconds(10));
  40. cache.Set(cacheKey, actionResult, cacheOptions);
  41. }
  42. context.Result = resultContext.Result;
  43. }
  44. }
复制代码
在program类中要注入MemoryCache
  1. builder.Services.AddMemoryCache();
复制代码
还要进行配置我们刚才写的筛选器
  1. builder.Services.AddControllers().AddMvcOptions(option => {
  2. option.Filters.Add(typeof(ResourceFilter));
  3. });
复制代码
在需要进行缓存的action头上加上ResourceFilter特性,表示这个action的返回结果要进行缓存
  1. [Route("api/[controller]/[action]"), ApiController]
  2. public class TestController : ControllerBase
  3. {
  4. List<SysUser> sysUsers = new List<SysUser>()
  5. {
  6. new SysUser("admin","123"),
  7. new SysUser("admin2","123")
  8. };
  9. [HttpGet, ResourceFilter]
  10. public List<SysUser> GetUsers() { return sysUsers; }
  11. }
  12. public record SysUser(string loginName,string loginPwd);
复制代码
进行测试,我这里直接就是截图的第二次请求,可以看到,请求去缓存里面读到了数据

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

来源:https://www.cnblogs.com/cyfj/archive/2023/11/07/17815126.html
免责声明:由于采集信息均来自互联网,如果侵犯了您的权益,请联系我们【E-Mail:cb@itdo.tech】 我们会及时删除侵权内容,谢谢合作!

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x
来自手机

举报 回复 使用道具