P7-5 筛选器

筛选器


什么是筛选器(Filter)

  • 1、切面编程机制,在ASP.NET-Core特定的位置执行我们自定义的代码。
    • 在ASP.NET-Core中,切面编程(Aspect-Oriented Programming, AOP)是一种编程范式,它允许开发者将横切关注点(如日志记录、事务管理、权限检查等)与业务逻辑分离,从而提高代码的模块化和可维护性。
  • 2、ASP.NET-Core中的Filter的五种类型:
    • 授权筛选器(Authorization filter):在执行动作方法之前检查用户是否有权限执行该操作。
    • 资源筛选器(Resource filter):在执行动作方法之前和之后执行代码,可以用于执行诸如日志记录、错误处理等任务。
    • 操作筛选器(Action filter):在动作方法执行之前和之后执行代码,通常用于修改动作方法的输入参数或处理动作方法的返回值。
    • 异常筛选器(Exception filter):在请求处理过程中捕获和处理异常。
    • 结果筛选器(Result filter):在动作方法执行并返回结果之后执行代码,可以用于修改返回给客户端的结果。
    • 本课程重点讲解异常筛选器操作筛选器
  • 3、所有筛选器一般有同步和异步两个版本,比如IActionFilter、IAsyncActionFilter接口。
    • 重点讲解异步筛选器

异常筛选器(Exception filter)

  • 当系统中出现未经处理的异常的时候,异常筛选器就会执行,我们可以在异常筛选器中对异常进行处理
    • 显示异常堆栈
  • 1、当系统中出现未处理异常的时候,我们需要统一给客户端返回如下格式的响应报文:{“code”:”500”,”message”:”异常信息”}。
    • 如果程序是在开发环境运行,则异常信息的内容为全部异常堆栈,否则异常信息的内容固定为“程序中出现未处理异常”
    • 在生产环境中,我们不能显示异常堆栈,以避免泄漏程序的机密信息
  • 2、实现IAsyncExceptionFilter接口。注入IHostEnvironment 得知运行环境。
    1
    2
    3
    4
    5
    6
    7
    //context.Exception代表异常信息对象
    //如果给context.ExceptionHandled赋值为true,则其他ExceptionFilter不会再被执行
    //context.Result的值会被输出给客户端
    ObjectResult result = new ObjectResult(new { code = 500, message = message });
    result.StatusCode = 500;
    context.Result = result;
    context.ExceptionHandled = true;
  • 3、全局筛选器
    1
    2
    3
    4
    5
    6
    builder.Services.Configure<MvcOptions>(options =>//多个Filter的时候,注意注册的前后位置
    {
    //options.Filters.Add<LogExceptionFilter>();
    options.Filters.Add<MyExceptionFilter>();
    options.Filters.Add<LogExceptionFilter>();
    });
  • 实例代码
    • 使用
  • 模拟生产环境的效果
    • 生产环境

操作筛选器基础(Action filter)

每次ASP.NET-Core中控制器的操作方法执行的时候,操作筛选器都会被执行,我们可以在操作方法执行之前和执行方法之后执行一些代码,完成特定的功能

  • 1、操作筛选器一半实现IAsyncActionFilter接口
  • 2、多个Action Filter的链式执行。
    • 筛选器1–>筛选器2–>筛选器3 用next来对接
      • 这是前代码
    • 筛选器3–>筛选器2–>筛选器1
      • 这是后代码
    • 模型
    • 测试
      • 成功
  • 3、无论是同步还是异步的操作筛选器,都可以处理同步和异步的操作方法,区别在于操作筛选器的实现代码是同步代码还是异步代码。
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    public async Task OnActionExecutionAsync(ActionExecutingContext context, ActionExecutionDelegate next)
    {
    Console.WriteLine("MyActionFilter 1:开始执行");//前代码
    ActionExecutedContext r = await next();
    if (r.Exception !=null)//后代码
    {
    Console.WriteLine("MyActionFilter 1:执行失败");
    }
    else
    {
    Console.WriteLine("MyActionFilter 1:执行成功");
    }
    }

案例:自动启用事务的操作筛选器

  • 数据库事务有一个非常重要的特性,那就是原子性,它保证了我们低数据库的多个操作要么全部成功,要么全部失败,进而帮助我们保证业务数据的正确性。
  • 但是,事务的使用是比较麻烦的,需要我们手工启用,提交及回滚事务,我们的业务代码中会充斥着事务管理的代码。针对于上述问题,我们需要实现一个对于数据库操作自动启用事务的操作筛选器。

需求

  • 1、数据库事务:要么全部成功、要么全部失败。
  • 2、自动化:启动、提交以及回滚事务。
  • 3、当一段使用EF Core进行数据库操作的代码放到TransactionScope声明的范围中的时候,这段代码就会自动被标记为“支持事务”。
  • 4、TransactionScope实现了IDisposable接口,如果一个TransactionScope的对象没有调用Complete()就执行了Dispose()方法,则事务会被回滚,否则事务就会被提交。
  • 5、TransactionScope还支持嵌套式事务。
  • 6、.NET-Core中的TransactionScope不像.NET Framewprk一样有MSDTC分布式事务提升的问题。请使用最终一致性事务。(具体可以看书里面的描述)

实现

用法

  • 1、对于强制不进行事务控制的Action方法,请标注NotTransactionalAttribute。
  • 2、开发筛选器TransactionScopeFilter;把TransactionScopeFilter注册到Program.cs中。
  • 3、编写两个插入数据的代码,测试。

同步方式与异步方法

  • 异步方法需要加上“TransactionScopeAsyncFlowOption.Enabled”
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    [HttpGet]
    public string Test1()//同步方法
    {
    //ThreadLocal: 相当于当前线程的全局变量(上下文)
    using (TransactionScope tx = new TransactionScope())//在TransactionScope范围中,默认标记为“支持事务”
    {
    dbCtx.Books.Add(new Book { Name = "NET", Price = 2 });
    dbCtx.SaveChanges();//一个事务
    dbCtx.Persons.Add(new Person { Name = "666666", Age = 2 });
    dbCtx.SaveChanges();//一个事务
    tx.Complete();
    return "ok";
    }

    }
    [HttpGet]
    public async Task<string> Test2()//异步方法
    {
    //AsyncLocal:相当于当前异步流程的全局变量(上下文)
    using (TransactionScope tx = new TransactionScope
    (TransactionScopeAsyncFlowOption.Enabled))
    {
    dbCtx.Books.Add(new Book { Name = "NET", Price = 2 });
    await dbCtx.SaveChangesAsync();//一个事务
    dbCtx.Persons.Add(new Person { Name = "666666", Age = 2 });
    await dbCtx.SaveChangesAsync();//一个事务
    tx.Complete();
    return "ok";
    }

    }

案例:开发请求限流器

需求

  • 1、Action Filter可以在满足条件的时候终止操作方法的执行。

  • 2、在Action Filter中,如果我们不调用await next(),就可以终止Action方法的执行了。

  • 3、为了避免恶意客户端频繁发送大量请求消耗服务器资源,我们要实现“一秒钟内只允许最多有一个来自同一个IP地址的请求”。

  • 限流器

注意

  • 实现项目中,一般限速不放在应用服务器这边,一般会放在前端的网关服务器上
    • 所以一般限速不会再业务代码中来实现,如果需要可以对该代码进行对应的改造

P7-5 筛选器
http://example.com/2024/10/11/Net Core2022教程/第7章:ASP.NET Core 基础组件/P7-5 筛选器/
Author
John Doe
Posted on
October 11, 2024
Licensed under