https://docs.microsoft.com/en-us/aspnet/core/mvc/controllers/filters?view=aspnetcore-5.0
使用.netcore 的过滤器
直接继承ActionFilterAttribute,重写方法OnActionExecutionAsync和SetResultToCacheAsync
/// <summary> /// 接口请求缓存过滤器 /// </summary> public class ActionCacheFilterAttribute : ActionFilterAttribute { private readonly ICacheService m_cacheService; private readonly int m_cacheTime; private string m_key; private readonly string[] m_names; private static readonly ILogger _logger = GlobalLogger.FromCurrentType(); /// <inheritdoc /> public ActionCacheFilterAttribute(int cacheTime, string[] names, ICacheService cacheService) { m_cacheTime = cacheTime; m_names = names; m_cacheService = cacheService; } /// <inheritdoc /> public override async Task OnActionExecutionAsync(ActionExecutingContext context, ActionExecutionDelegate next) { // 执行前 if (await TrySetResultByCacheAsync(context)) { return; } var executedContext = await next(); // 执行后 await SetResultToCacheAsync(executedContext); } /// <summary> /// 将结果放到缓存中 /// </summary> /// <param name="context"></param> public async Task SetResultToCacheAsync(ActionExecutedContext context) { var result = context.Result as ObjectResult; if (context.Exception == null && result?.Value != null) { await m_cacheService.SetAsync(m_key, context.Result, new CacheEntryOptions { AbsoluteExpirationRelativeToNow = TimeSpan.FromMinutes(m_cacheTime) }); } } /// <summary> /// 尝试将缓存结果赋值到接口的结果 /// </summary> /// <param name="context"></param> public async Task<bool> TrySetResultByCacheAsync(ActionExecutingContext context) { SetCacheKey(context); var result = await m_cacheService.GetAsync<ObjectResult>(m_key); if (result == null) return false; context.Result = result; return true; } private void SetCacheKey(ActionExecutingContext context) { context.RouteData.Values.TryGetValue("action", out var action); context.RouteData.Values.TryGetValue("controller", out var controller); var parameter = context.ActionArguments.Values.First().ToJson(); var jb = (JObject)JsonConvert.DeserializeObject(parameter); var cacheKey = new StringBuilder() .Append(controller) .Append(action); m_names.ToList().ForEach(x => cacheKey.Append(jb[x])); m_key = cacheKey.ToString(); _logger.Trace($"{action} request: {parameter}"); } }
在需要使用的控制器方法中写上标签
[ServiceFilter(typeof(ActionCacheFilterAttribute))]
注入
Services.AddScoped<ActionCacheFilterAttribute
>();
这种只能在没有属性的标签中使用
当我们的标签有自身的属性我们可以用 [TypeFilter(typeof(ActionCacheFilterAttribute), Arguments = new object[] { 1, new[] { "EventId", "Radius" , "LayerName" } })] ,arguments对应的就是标签中的属性字段。