Filter --ResourceFilter --ActionFilter - 做aop
1.Authorize
2.ResourceFilter
3.ActionFilter
4.Result
5.AlwaysRunResult
6.Exception
只要是框架提供给我们的是接口、抽象类,天生就是为了让我我们来扩展的
1 ResourceFilter 就是做缓存用的 接口IResourceFilter IAsyncResourceFilter
执行顺序 就是用OnResourceExecuting 和 OnResourceExecuted 方法把控制器的构造函数+action给包裹起来了
ResourceFilter也有AsyncResourceFilter ---执行结果和同步版本是一致的;
正常的顺序是 : 控制器的构造函数——————》自己写的方法action————》完成
加上 [CustomResourceFilter] 特性以后 执行顺序: OnResourceExecuting————》 控制器的构造函数——————》自己写的方法action————》OnResourceExecuted———》完成
写async 版本的ResourceFilter 把路径缓存下来
public class CustomAsyncResourceFilterAttribute : Attribute, IAsyncResourceFilter { //ResourceFilter 就是为了做缓存用的 private static Dictionary<string, object> CacheDictionary = new Dictionary<string, object>(); /// <summary> /// 在资源执行的时候 /// /// 扩展缓存: /// 1.一组数据保存在内存中 /// 2.存储数据的标识---存数据---把标识附上去,取数据也可以通过这个标识直接去去 /// 3.缓存有数据,且标识不变---取到的缓存数据也不变 /// </summary> /// <param name="context"></param> /// <param name="next"></param> /// <returns></returns> public async Task OnResourceExecutionAsync(ResourceExecutingContext context, ResourceExecutionDelegate next) { { Console.WriteLine("OnResourceExecutionAsync OnResourceExecutingAsync"); // action执行前就发生 } string key = context.HttpContext.Request.Path; //在这里就应该检查缓存 可以检查redis //1.如果有缓存,就应该直接响应给前端了,不再继续往后,如果没有--就执行next.Invoke(); if (CacheDictionary.ContainsKey(key)) { object oResult = CacheDictionary[key]; context.Result = (IActionResult)oResult;// context.Result 类似于一个断路器,只要对context.Result赋值,就不再继续往后执行了 } else { ResourceExecutedContext executedContext= await next.Invoke(); // action执行 CacheDictionary[key] = executedContext.Result; } // await next.Invoke(); // action执行 { Console.WriteLine("OnResourceExecutionAsync ResourceExecuted"); // action完成后发生 } } }
ResourceFilter 的全局注册
public void ConfigureServices(IServiceCollection services) { //services.AddControllersWithViews(); #region 全局注册Filter services.AddControllersWithViews( option => { option.Filters.Add<CustomResourceFilterAttribute>(); //全局注册CustomResourceFilterAttribute } ).AddControllersAsServices(); #endregion }
全局 控制器 action 全部都注册以后的执行顺序
1全局:OnResourceExecuting 外
2控制器类:OnResourceExecuting 中
3Action方法:OnResourceExecuting 里
4开始实例化控制器 核心
5开始执行Action方法 核心
6Action方法上的:OnResourceExecuted 里
7控制器类:OnResourceExecuted 中
8全局:OnResourceExecuted 外
2ActionFilter IActionFilter IAsyncActionFilter ActionFilterAttribute 最适合做日志
执行顺序
1.实例化控制器
2.执行CustomActionFilterAttribute.------OnActionExecuting
3.执行action方法
4.执行CustomActionFilterAttribute--------OnActionExecuted
actionFilter 在你检查OnActionExecuting时候 已经实例化类了,所以不适合做缓存,