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对应的就是标签中的属性字段。
posted on 2021-02-07 11:43  ccc#  阅读(80)  评论(0编辑  收藏  举报