首页 > 其他分享 >WebApi过滤器初学习

WebApi过滤器初学习

时间:2024-06-06 09:00:36浏览次数:21  
标签:WebApi void 学习 context 过滤器 path logger public

WebApi 过滤器

Authorization Filters  //权限验证
Resource Filters   //资源验证   常被用于缓存
Model Binding  //模型绑定
Action Filters  //行为   常被用于模型验证和日志记录
Exception Filters  //异常处理  常被用于错误日志
Result Filters    //结果验证  用于

三种注册方式

  • 方法注册 注册在方法上 Action
  • 类注册 注册在控制器上 Controller
  • 全局注册 注册在Program

过滤器的注解的定义

 public class CtmResourceFilterAttribute : Attribute, IResourceFilter
 {
     public void OnResourceExecuted(ResourceExecutedContext context)
     {
         throw new NotImplementedException();
     }
     //控制器请求前,可以有效减少服务器的压力
     public void OnResourceExecuting(ResourceExecutingContext context)
     {
         //可以添加短路器
         throw new NotImplementedException();
     }
 }
 public class CtmAuthriztionFuilterAttribute : Attribute, IAuthorizationFilter
 {
     //在请求完成前
     public void OnAuthorization(AuthorizationFilterContext context)
     {
         throw new NotImplementedException();
     }
 }
  public class CtmActionFilterAttribute : Attribute, IActionFilter
  {
      //请求结束后
      public void OnActionExecuted(ActionExecutedContext context)
      {
          throw new NotImplementedException();
      }
      //请求结束前
      public void OnActionExecuting(ActionExecutingContext context)
      {
          throw new NotImplementedException();
      }
  }

三种方法权重不一样,执行的依次顺序

progarm->类注册->方法注册

相同类型的FIlter,全局注册的优先级>类上注册优先级>方法上的优先级

不同类型的拦截器互不影响,按照图例顺序

方法注册

namespace FilterDemo.Controllers
{
    [ApiController]
    [Route("[controller]/[action]")]
    public class WeatherForecastController : ControllerBase
    {
        private readonly ILogger<WeatherForecastController> _logger;
        public WeatherForecastController(ILogger<WeatherForecastController> logger)
        {
            _logger = logger;
        }
        [HttpGet]
        [CtmActionFilter]//行为拦截
        [CtmAuthriztionFuilter]//鉴权
        public string Get()
        {
            return "";
        }
    }
}

类注册

namespace FilterDemo.Controllers
{
    [ApiController]
    [Route("[controller]/[action]")]
    [CtmActionFilter]//行为拦截
    [CtmAuthriztionFuilter]//鉴权
    [CtmResourceFilter]//资源拦截
    public class WeatherForecastController : ControllerBase
    {

        private readonly ILogger<WeatherForecastController> _logger;

        public WeatherForecastController(ILogger<WeatherForecastController> logger)
        {
            _logger = logger;
        }

        [HttpGet]
        public string Get()
        {
            return "";
        }

    }
}

Progarm注册

builder.Services.AddControllers(o=>o.Filters.Add<CtmActionFilterAttribute>());
  builder.Services.AddControllers(o=> { 
      //数字越小,越先执行
      o.Filters.Add<CtmActionFilterAttribute>(1);
      o.Filters.Add<CtmActionFilterAttribute>(2);
  });

过滤器的执行顺序

在方法注册上添加order比重

[HttpGet]
// [CtmActionFilter]//行为拦截
[CtmAuthriztionFuilter]//鉴权
[TypeFilter(typeof(CtmResourceFilterAttribute))]//资源拦截
[TypeFilter(typeof(CtmExceptionFilterAttriubute))]//异常处理拦截
[CtmResultFilter]
//在特性中,第一个是作为构造函数传入的,第二个是给属性传参,要把属性的名称填上
[TypeFilter(typeof(CtmActionFilterAttribute),Order =1)]
public string Get()
{
    return "";
}

就算是全局定义的filter,如果自行定义的order没有方法注册的比重大,那么,仍然要先执方法注册的

授权过滤器

AuthorizationFilter

过滤器管道中的第一个过滤器。

控制对操作方法的访问。

这是一个简单的模拟,目的是拿取参数中的值

短路器

前置过滤器有AuthorizationFilter和ResouceFilter,这两个过滤器是指在控制器的构造函数执行之前执行的,这两个过滤器执行后,执行构造函数,在执行Model Binding模型绑定和ActionFilter

ResourceFilter

其中Result正常来说为null,如果不等于null,正常来说,应该是短路器被触发了。

短路器被触发后,就不会去触发控制器的构造函数了,会直接通过短路器的内部逻辑返回请求。

 public class CtmResourceFilterAttribute : Attribute, IResourceFilter
 {
     private static Dictionary<string, object> _dicCache = new Dictionary<string, object>();
     //控制器处理请求后
     public void OnResourceExecuted(ResourceExecutedContext context)
     {
         //获取当前访问的网址
         PathString path = context.HttpContext.Request.Path;
         //将返回的数据存在数组中
         _dicCache[path] = context.Result as ObjectResult;
     }
     //控制器请求前,可以有效减少服务器的压力
     public void OnResourceExecuting(ResourceExecutingContext context)
     {
         //可以添加短路器,这里就触发短路了
         //context.Result = new JsonResult("没有权限");

         //获取当前的访问地址
         var path = context.HttpContext.Request.Path;
         //字典中是否包含path
         if (_dicCache.ContainsKey(path))
         {
             //如果包含,直接返回缓存的数据
             context.Result = _dicCache[path] as ObjectResult;
         }
        
     }
 }

ActionFilter

用于 记录日志,模型认证

以下代码讲的是,如何用ActionFilter去记录日志和特性注入

过滤器实现构造函数注入

[HttpPost]
[TypeFilter(typeof(CtmActionFilterAttribute))]
public User AddUser(User user)
{
    return user;
}
 //一个特性,关于方法的拦截
 public class CtmActionFilterAttribute : Attribute, IActionFilter
 {
     private readonly ILogger logger;

     public CtmActionFilterAttribute(ILogger<CtmActionFilterAttribute> logger)
     {
         this.logger = logger;
     }


     //请求结束后
     public void OnActionExecuted(ActionExecutedContext context)
     {
         throw new NotImplementedException();
     }
     //请求结束前
     public void OnActionExecuting(ActionExecutingContext context)
     {
         logger.LogInformation("....");
     }
 }

还有一种注册方式

 [HttpPost]
 [ServiceFilter(typeof(CtmActionFilterAttribute))]
 public User AddUser(User user)
 {
     return user;
 }

这种方式需要将filter在Progarm中进行依赖注册

builder.Services.AddTransient<CtmActionFilterAttribute>();
//这里注册的是Transient,瞬态

如果使用了ServiceFilter,那么无论是Filter本身还是filter需要注入的参数,都需要在容器中注入。

 builder.Services.AddTransient<User>();
public class CtmActionFilterAttribute : Attribute, IActionFilter
{
    private readonly ILogger logger;
    private readonly User user;

    public CtmActionFilterAttribute(ILogger<CtmActionFilterAttribute> logger,User user)
    {
        this.logger = logger;
        this.user = user;
    }


    //请求结束后
    public void OnActionExecuted(ActionExecutedContext context)
    {
        throw new NotImplementedException();
    }
    //请求结束前
    public void OnActionExecuting(ActionExecutingContext context)
    {
   
        PathString path = context.HttpContext.Request.Path;
        var argumnet = context.ActionArguments;

        if (argumnet.ContainsKey("User"))
        {
            var user = argumnet["user"] as User;
            logger.LogInformation($"{user.Name} is visiting {path}");

        }
        else
        {
            logger.LogInformation($"{user.Name} is visiting {path}");
        }

    }

利用缓存实现短路

缓存使用menory catch

首先要对menory catch进行注册

注意注册时,不能用瞬态,使用单例模式,保持缓存的存在

builder.Services.AddSingleton<IMemoryCache,MemoryCache>();

对控制器使用

        [HttpGet]
        // [CtmActionFilter]//行为拦截
        [CtmAuthriztionFuilter]//鉴权
        [TypeFilter(typeof(CtmResourceFilterAttribute))]//资源拦截
        public string Get()
        {
            return "";
        }

这样才能在ResourceFilterAttribute中拿到相应的缓存

using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Filters;
using Microsoft.Extensions.Caching.Memory;

namespace FilterDemo.Filters
{
    public class CtmResourceFilterAttribute : Attribute, IResourceFilter
    {
        private static Dictionary<string, object> _dicCache = new Dictionary<string, object>();
        private readonly IMemoryCache memoryCache;

        //控制器处理请求后
        public CtmResourceFilterAttribute(IMemoryCache memoryCache)
        {
            this.memoryCache = memoryCache;
        }
        public void OnResourceExecuted(ResourceExecutedContext context)
        {
            /* //获取当前访问的网址
             PathString path = context.HttpContext.Request.Path;
             //将返回的数据存在数组中
             _dicCache[path] = context.Result as ObjectResult;*/


            //获取当前访问的网址
            PathString path = context.HttpContext.Request.Path;
            //不再用字典,用缓存进行存储返回的结果
            //两个参数,一个key一个value
            memoryCache.Set(path, context.Result as ObjectResult); 


        }
        //控制器请求前,可以有效减少服务器的压力
        public void OnResourceExecuting(ResourceExecutingContext context)
        {
            //可以添加短路器,这里就触发短路了
            //context.Result = new JsonResult("没有权限");
            //获取当前的访问地址
            var path = context.HttpContext.Request.Path;
            //字典中是否包含path
           /* if (_dicCache.ContainsKey(path))
            {
                //如果包含,直接返回缓存的数据
                context.Result = _dicCache[path] as ObjectResult;
            }*/
           

            //从缓存中拿到当前path对应的值
            //有值返回true,没有值返回false
            if(memoryCache.TryGetValue(path,out object value))
            {
                context.Result = value as ObjectResult;
            }
        }
    }
}

关于out

  if(memoryCache.TryGetValue(path,out object value))
   {
      context.Result = value as ObjectResult;
   }

解析版

 object value;
 if(memoryCache.TryGetValue(path,out value))
  {
      context.Result = value as ObjectResult;
  }

给参数赋值后,加上out,可以将返回值,和加上out修饰的值一并带出来。

ExceptionFilters

异常处理拦截

作用是捕获异常的处理

using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Filters;

namespace FilterDemo.Filters
{
    public class CtmExceptionFilterAttriubute : Attribute, IExceptionFilter
    {
        private readonly ILogger<CtmExceptionFilterAttriubute> logger;

        public CtmExceptionFilterAttriubute(ILogger<CtmExceptionFilterAttriubute> logger)
        {
            this.logger = logger;
        }
        //在这里可以拿到错误信息
        public void OnException(ExceptionContext context)
        {
            logger.LogInformation(context.Exception.Message);
            context.Result = new ContentResult
            {
                Content = context.Exception.Message
            };
        }
    }
}

 [HttpGet]
 // [CtmActionFilter]//行为拦截
 [CtmAuthriztionFuilter]//鉴权
 [TypeFilter(typeof(CtmResourceFilterAttribute))]//资源拦截
 [TypeFilter(typeof(CtmExceptionFilterAttriubute))]//异常处理拦截
 public string Get()
 {
     return "";
 }

异常过滤器的捕获范围

可以用于常见的错误处理策略

非常适合捕获发生在操作中的异常

建议使用中间件的处理异常

基于所调用的操作方法,仅当错误处理不同时,才使用异常过滤器。

只能捕获跟action相关的异常,只能捕获操作相关的异常

捕获范围很小

ResultFilters

结果过滤器,围绕着操作结果执行。

只有当操作能够生成结果时,才会使用结果过滤器。

在异常过滤器通过生成操作结果时,结果过滤器不会执行。

结果过滤器中的异常不会被异常过滤器捕获

但是如果继承了IAlwaysRunResultFilter接口,那么就可以在异常过滤器捕获异常后仍然可以进入结果过滤器

using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Filters;

namespace FilterDemo.Filters
{
    public class CtmAlwaysResultFilter : Attribute, IAlwaysRunResultFilter
    {
        public void OnResultExecuted(ResultExecutedContext context)
        {
            throw new NotImplementedException();
        }

        public void OnResultExecuting(ResultExecutingContext context)
        {
            if (context.Result is StatusCodeResult statusCodeResult
                && statusCodeResult.StatusCode == StatusCodes.Status404NotFound)
            {
                context.Result = new ObjectResult("这是404")
                {
                    StatusCode = StatusCodes.Status404NotFound
                };
            }
        }
    }
}

标签:WebApi,void,学习,context,过滤器,path,logger,public
From: https://www.cnblogs.com/guan-tou6/p/18234380

相关文章

  • 期权学习范畴
    视频从零开始学期权-期权初级https://www.bilibili.com/video/BV13J411m7JL/?spm_id_from=333.337.search-card.all.click&vd_source=debae4e77e1cafd283cb9668d2acb3a7从零开始学期权——期权中级https://www.bilibili.com/video/BV1tK4y1j747/?spm_id_from=333.999.0.0&v......
  • 如何学习提示词?
    随着人工智能技术的飞速发展,AI已经成为我们生活中不可或缺的一部分。从智能助手到专业领域的应用,AI正在以前所未有的速度和规模改变着我们的工作与生活。而在AI的众多应用中,提示词(Prompt)的作用日益凸显。提示词,简而言之,就是引导AI进行特定任务的指令或问题。它的重要性不言而喻......
  • 分布式搜索引擎ElasticSearch学习笔记
    一、Elasticsearch介绍什么是elasticsearch?一个开源的分布式搜索引擎,可以用来实现搜索、日志统计、分析、系统监控等功能什么是elasticstack(ELK)?是以elasticsearch为核心的技术栈,包括beats、Logstash、kibana、elasticsearch什么是Lucene?是Apache的开源搜索引擎类库,提......
  • JVM学习-内存泄漏
    内存泄漏的理解和分类可达性分析算法来判断对象是否是不再使用的对象,本质都是判断一上对象是否还被引用,对于这种情况下,由于代码的实现不同就会出现很多内存泄漏问题(让JVM误以为此对象还在引用,无法回收,造成内存泄漏)内存泄漏(memoryleak)严格来说,只有对象不会再被程序......
  • 完全指南:C语言学习资源汇总
    C语言是编程学习的基石,无论是为了职业发展还是个人兴趣,掌握C语言都是技术生涯的重要一步。为了帮助初学者和有经验的程序员更好地学习和深化对C语言的理解,我们汇总了一系列优秀的书籍和在线资源。这些资源将帮助你从基础知识到高级概念,全面掌握C语言。推荐书籍1.《C语言入门......
  • JVM学习-监控工具(一)
    使用数据说明问题,使用知识分析问题,使用工具处理问题无监控,不调优!命令行工具在JDK安装目录下,可以查看到相应的命令行工具,如下图jps(JavaProcessStatus)显示指定系统内所有的Hotpot虚拟机进程,可用于查询正在运行的虚拟机进程,对于本地虚拟机进程来说,进程的本地虚拟机ID......
  • 算法金 | 10 大必知的自动化机器学习库(Python)
    大侠幸会,在下全网同名[算法金]0基础转AI上岸,多个算法赛Top[日更万日,让更多人享受智能乐趣]一、入门级自动化机器学习库1.1Auto-Sklearn简介:Auto-Sklearn是一个自动机器学习库,基于Python的scikit-learn接口。它主要用于自动化机器学习的常见过程,特别是算法选......
  • 机器学习与量化交易 分类任务
     >Julyedu.com感谢白嫖的七月在线专注数据领域的在线教育01自动化交易综述时间序列分析策略建模及其优化方法策略评价与回测风险管理交易策略的实现交易策略的执行BP(BackProppagation)算法误差反向传播(ErrorBackPropagation,BP)算法。学习过程由信号的正向传......
  • Day1 学习笔记及成果---MapReduce实现手机流量统计分析
    Day1学习笔记及成果—MapReduce实现手机流量统计分析题目统计每个手机号上行流量和、下行流量和、总流量和(上行流量和+下行流量和),并且:将统计结果按照手机号的前缀进行区分,并输出到不同的输出文件中去。13*==>…15*==>…other==>…其中,access.log数据文件部分......
  • Day2 学习笔记及成果---基于MapReduce项目实现中所遇到的问题及解决方法
    Day2学习笔记及成果—基于MapReduce项目实现中所遇到的问题及解决方法问题一:主机和虚拟机互相能ping通,主机能ping通外网,虚拟机不能ping通外网。解决方案:可能的错误原因是网关设置有问题,虚拟机的网关应该和自己的网关一直,自己的网关可在编辑-虚拟网络设置中查看。首先执......