• 7.6中间件


    7.6中间件

    ASP.NET Core只是完成了HTTP请求调度、报文解析等必要的工作,像检查用户身份、设置缓存报文头等操作都是在中间件中完成,中间件就是ASP.NET Core的一个组件,由前逻辑、next、后逻辑3部分组成,多个中间件组成一个管道,一个系统中可以有多个管道。ASP.NET Core执行的过程就是http请求和响应按照中间件组装的顺序在中间件之间流转的过程。

    img

    管道引入中间件

    WebApplication针对中间件具有3个重要的概念,Map、Use、Run。Map是用来引入请求的,请求来到管道后,组成管道的多个Use负责对请求进行预处理,Run负责主要的业务规则。

    方法作用
    Map定义一个管道可以处理哪些请求
    Use每个Use引入一个中间件,一个管道有若干个Use
    Run执行最终的业务逻辑,一般一个管道中只包含一个Run方法且在最后,因为Use引入的中间件可以把请求转到下一个中间件,但是执行Run方法处理就终止了

    中间件演示

    创建ASP.NET Core空项目,在Program.cs中添加:

    var builder = WebApplication.CreateBuilder(args);
    var app = builder.Build();
    //定义了对/test路径请求的处理,4-22为一个管道
    app.Map("/test", async appbuilder => {
        //声明第一个中间件
        appbuilder.Use(async (context, next) => {
            context.Response.ContentType = "text/html";
            await context.Response.WriteAsync("1  Start
    "
    ); await next.Invoke();//执行下一个中间件 await context.Response.WriteAsync("1 End
    "
    ); }); //声明第二个中间件 appbuilder.Use(async (context, next) => { await context.Response.WriteAsync("2 Start
    "
    ); await next.Invoke(); await context.Response.WriteAsync("2 End
    "
    ); }); //中间件执行完成后,执行run appbuilder.Run(async ctx => { await ctx.Response.WriteAsync("hello middleware
    "
    ); }); }); app.Run(); //注意,如果在中间件中使用ctx.Response.WriteAsync等方式向客户端发送响应,我们就不能 //再执行next.Invoke了把请求转到其他中间件了,因为其他中间件可能会对response进行了修改 //该案例仅仅当做演示
    • 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

    请求/test结果如下:

    在这里插入图片描述

    中间件类

    中间件类是一个普通的类,该类中需要一个构造方法,构造方法至少有一个RequestDelegate类型参数,该参数用来指向下一个中间件。类中还需要Invoke或者InvokeAsync的方法,方法中至少有一个HttpContext类型参数,返回值为Task类型。

    public class CheckAndParsingMiddleware
    {
        private readonly RequestDelegate next;
        public CheckAndParsingMiddleware(RequestDelegate next)
        {
            this.next = next;
        }
    	//中间件的前逻辑、next、后逻辑都在这里
        public async Task InvokeAsync(HttpContext context)
        {
            string pwd = context.Request.Query["password"];
            if (pwd=="123")
            {
                context.Items["BodyJson"] = "hellowrld";
                await next(context);//传递到下一个中间件
            }
            else
            {
                context.Response.StatusCode = 401;//不会传递到下一个中间件
            }
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22

    Program.cs

    var builder = WebApplication.CreateBuilder(args);
    var app = builder.Build();
    app.Map("/test", async appbuilder => {
        appbuilder.UseMiddleware<CheckAndParsingMiddleware>();//按注册顺序,执行中间件类的Invoke方法
        appbuilder.Run(async ctx => {
            Console.WriteLine("run start");
            ctx.Response.ContentType = "text/html";
            ctx.Response.StatusCode = 200;
            //HttpContext.Item在同一次请求中是共享的,用它来实现中间件之间数据的传递
            await ctx.Response.WriteAsync(ctx.Items["BodyJson"].ToString());
            Console.WriteLine("run end");
        });
    });
    app.Run();
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    除了请求匹配的Map方法还有匹配Get请求的MapGet方法,匹配Post请求的MapPost方法。并且通过MapWhen方法中的Func参数可以过滤请求。

    //报文头中AAA的值为123的请求所对应的管道
    app.MapWhen(ctx => ctx.Request.Headers["AAA"]=="123",async appbuilder =>{});
    //请求路径以/api开头的所对应的管道
    app.MapWhen(ctx => ctx.Request.Path.StartsWithSegments("/api"),async appbuilder =>{});
    
    • 1
    • 2
    • 3
    • 4

    中间件的组装顺序很重要,并且asp.net里面有很多内置的中间件在使用的时候一定要仔细阅读中间件组装顺序说明

    筛选器和中间件的区别

    ASP.NET Core MVC是由MVC中间件提供的框架,而筛选器数据MVC中间件中的功能

    中间件筛选器
    ASP.NET Core提供的功能ASP.NET Core MVC提供的功能
    可以处理所有请求(控制器请求,静态文件等)只能针对控制器的请求
    无法处理IActionResult、ActionDescriptor等MVC特有概念可以处理MVC框架中的概念
    效率更高、范围更广、更底层

    建议能使用中间件的情况尽量使用中间件,如果中间件和过滤器同时使用,则会先执行完所有的中间件前逻辑,然后执行过滤器,最后执行中间件的后逻辑。
    在这里插入图片描述

  • 相关阅读:
    性能测试常见分类
    经典算法-枚举法(百钱买百鸡问题)
    C. Mr. Perfectly Fine
    [附源码]Python计算机毕业设计Django网约车智能接单规划小程序
    所有社区工作者!能救一个是一个
    SpringCloud&Gateway理论与实践
    探究——C# .net 代码混淆/加壳
    Java大数 -- BigInteger类
    读高性能MySQL(第4版)笔记19_云端和合规性
    异地远程访问内网BUG管理系统【Cpolar内网穿透】
  • 原文地址:https://blog.csdn.net/weixin_44064908/article/details/126548403