• ASP.NET WebAPI 13 Filter


    Filter(筛选器)是基于AOP(面向方面编程)的设计,它的作用是Actionr的执行注入额外的逻辑,以达到横切注入的目的。

    IFilter

    在WebAPI中所以的Filter都实现了IFilter接口 ,IFilter接口只有一个只读属性AllowMultiple,它表示同类的Filter是否可以应用到同一目标对象上。

     

    public interface IFilter
    
    { 
    
    bool AllowMultiple { get; } 
    
     }
    

    FilterInfo

    在HttpActionDescriptor与HttpControllerDescriptor中也存储了Action使用到的Filter。但它不是直接以IFilter的形式进行存储,也是以FilterInfo(System.Web.Http.Filters)。

     

    public sealed class FilterInfo
    
     {
    
    public FilterInfo(IFilter instance, FilterScope scope); 
    
    public IFilter Instance { get; } 
    
    public FilterScope Scope { get; } 
    
     }
    

    在FilterInfo中有两个属性:Instance,Scope。其中Instance是IFilter对象。在实际对Filter运用中我们应该注意并发的情况,因为对于同一个Filter调用的都是同一个Filter对象。  

    FilterScope

    对于FilterInfo类的Scope属性,它表示Filter的域。在WebAPI中Filter有3个域:Global,Controller,Action。

     

    public enum FilterScope
    
     { 
    
     Global = 0, 
    
     Controller = 10, 
    
     Action = 20, 
    
     }
    

    对于Controller,Action的Filter添加都是采用特性(Attribute)的方式。对于全局Filter是添加在HttpConfiguration的Filter。

    FilterProvider

    WebAPI提供了IFilterProvider(System.Web.Http.Filters)用于提供不同域下的Filter。

     

    public interface IFilterProvider
    
    {
    
    IEnumerable<FilterInfo> GetFilters(HttpConfiguration configuration, HttpActionDescriptor actionDescriptor); 
    
     }
    

    在WebAPI中FilterProvider也是"标准化组件",但是它是以multi的形式注入的.WebAPI中IFilter有两个默认实现: ConfigurationFilterProvider, ActionDescriptorFilterProvider,从命名上我们就可以知道前者是提供全局Filter,后者是提供Controller,Action的Filter。

    5类Filter

    WebAPI为我们定义了5类Filter。分别如下:

    AuthenticationFilter:用于请求认证(IAuthenticationFilter)。

    AuthorizationFilter:用于请求授权(IAuthorizationFilter)。

    ActionFilter:ActionFilter:注册的操作会在Action执行的前后被调用(IActionFilter)。

    ExceptionFilter:当目标Action抛出异常是调用(IExceptionFilter)。

    OverrideFilter:用于屏蔽当前域之前的Filter(IOverrideFilter)。

    本文重点讲后三类Filter,对于前两类,后续再做跟进。对于后三类Filter默认实现是ActionFilterAttribute,ExceptionFilterAttribute,OverrideActionFilterAttribute。如下:

     

    [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, Inherited = true, AllowMultiple = true)] 
    
    public abstract class ActionFilterAttribute : FilterAttribute, IActionFilter, IFilter
    
     {
    
    protected ActionFilterAttribute(); 
    
    public virtual void OnActionExecuted(HttpActionExecutedContext actionExecutedContext); 
    
    public virtual Task OnActionExecutedAsync(HttpActionExecutedContext actionExecutedContext, CancellationToken cancellationToken); 
    
    public virtual void OnActionExecuting(HttpActionContext actionContext); 
    
    public virtual Task OnActionExecutingAsync(HttpActionContext actionContext, CancellationToken cancellationToken); 
    
     }
    

     

    [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, Inherited = true, AllowMultiple = true)] 
    
    public abstract class ExceptionFilterAttribute : FilterAttribute, IExceptionFilter, IFilter
    
     { 
    
    protected ExceptionFilterAttribute(); 
    
    public virtual void OnException(HttpActionExecutedContext actionExecutedContext); 
    
    public virtual Task OnExceptionAsync(HttpActionExecutedContext actionExecutedContext, CancellationToken cancellationToken); 
    
     }
    
    [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, Inherited = true, AllowMultiple = false)] 
    
    public sealed class OverrideActionFiltersAttribute : Attribute, IOverrideFilter, IFilter
    
     { 
    
    public OverrideActionFiltersAttribute(); 
    
    public Type FiltersToOverride { get; } 
    
     }
    

    唯一性

    因为Filter有三个域,那么在采用特性标示的方式注入Filter的,必定有可能会对同一个Action上注入多个相同的Filter。显然在使用中一般不会允许这种情况发生。WebAPI中提供了相应的策略用来保证Filter的唯一性。即对FilterAttribute添加AttributeUsage特性,并将AllowMultiple设置为false.

    当然这个设置过后你会发现在三个域上我还是可以添加相同的Filter,那么这个时候WebAPI会为我们筛选出一个Filter去调用。筛选规则如下:

    Action>Controller>Global

    即FilterScope的值越大,优先级超高。

    ActionFilter

    ActionFilterAttribute提供了4个虚方法: OnActionExecuted,OnActionExecutedAsync,OnActionExecuting,OnActionExecutingAsync 其实两个异步方法只是对两个同步的方法的封装,所以我们一般只重写两个同步方法。

    在执行顺序上ActionFilter的规则是:

    1. 不同域:Global>ControllerAction
    2. 相同域:按照注入顺序执行

    在执行OnActionExecuting的过程中如果给actionContext.Response赋值,那么Filter管道就会做返回处理,不再去做后续操作。

    ExceptionFilter

    在执行Action与整个ActionFilter管道中,如果抛出异常,

    1. ExpceptionFilter的执行顺序与ActionFilter正好相反
    2. ExceptionFilter管道处理的是整个ActionFilter管道抛出的异常,并不是单纯的Action抛出的异常
    3. 如果在ExceptionFilter管道中抛出异常,那么该ExceptionFilter都不会执行。

    OverrideFilter

    一个Action的所有Filter是Global,Controller,Action三个域下的Filter的总合,但有些时候我们并想要上一级域的Filter这个时候就需要用到OverrideFilter。WebAPI的OverrideActionFiltersAttribute只会屏蔽IActionFilter,并不会对其它的Filter进行屏蔽。

    源码

    Github: https://github.com/BarlowDu/WebAPI (API_13)

  • 相关阅读:
    深入Eureka/Feign/Hystrix原理学习(1)
    mysql截取函数substring_index()和right()用法
    Mybatis映射文件的自动映射与手动映射问题
    MySQL单向加密函数
    Grovvy带参数的闭包
    微信小程序开发编程手记20190303
    IDEA 各版本在线激活(激活码)
    Vue实例:演示input 和 textarea 元素中使用 v-model 实现双向数据绑定
    mybatis异常解决:class path resource [SqlMapConfig.xml] cannot be opened because it does not exist
    【学亮IT手记】MySql行列转换案例
  • 原文地址:https://www.cnblogs.com/gangtianci/p/5001846.html
Copyright © 2020-2023  润新知