Net6的核心组件之中间件

What is Middleware?

1、广义上来讲:Tomcat、WebLogic、Redis、IIS;狭义上来讲,ASP.NET Core中的中间件指ASP.NET Core中的一个组件。
2、中间件由前逻辑、next、后逻辑3部分组成,前逻辑为第一段要执行的逻辑代码、next为指向下一个中间件的调用、后逻辑为从下一个中间件执行返回所执行的逻辑代码。每个HTTP请求都要经历一系列中间件的处理,每个中间件对于请求进行特定的处理后,再转到下一个中间件,最终的业务逻辑代码执行完成后,响应的内容也会按照处理的相反顺序进行处理,然后形成HTTP响应报文返回给客户端。
3、中间件组成一个管道,整个ASP.NET Core的执行过程就是HTTP请求和响应按照中间件组装的顺序在中间件之间流转的过程。开发人员可以对组成管道的中间件按照需要进行自由组合。

4、中间件是ASP.NET Core的核心组件,MVC框架、响应缓存、身份验证、CORS、Swagger等都是内置中间件。以下图是执行流程

image-1659778499491

中间件的三个概念(Map、Use、Run)

Map、Use和Run。Map用来定义一个管道可以处理哪些请求,Use和Run用来定义管道,一个管道由若干个Use和一个Run组成,每个Use引入一个中间件,而Run是用来执行最终的核心应用逻辑。

image-1659778519589

总结:

Map是接待客人(请求)的作用:告诉对应的请求,我这里可以处理 Use 是中间件,每一个Map就是一道门的守门员,门后面的功能由各个不同的中间件组成

Program

using MiddleWare;

var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();

//此时只能处理localhost的请求
app.MapGet("/", () => "Hello World!");

//自定义中间件测试MiddleWare
//一般不在Use里面输出内容  只在Run里面做此操作 这段代码仅仅做演示 
app.Map("/test", pilebuilder => {
    pilebuilder.Use(async (context,next) =>
    {
        //以下代码为前代码
        context.Response.ContentType = "text/html;charset=UTF-8";
        await context.Response.WriteAsync("1 start<br/>");
        //以上代码为前代码
        await next.Invoke();
        //以下代码为后代码
        await context.Response.WriteAsync("1 end<br/>");
        //以上代码为后代码
    });
    pilebuilder.Use(async (context, next) =>
    {
        //以下代码为前代码
        await context.Response.WriteAsync("2 start<br/>");
        //以上代码为前代码
        await next.Invoke();
        //以下代码为后代码
        await context.Response.WriteAsync("2 end<br/>");
        //以上代码为后代码
    });

    pilebuilder.Run(async context =>
    {
        //端点(终点)中间件
        await context.Response.WriteAsync(pw+"+Hellp MiddleWare<br/>");

    });
});
app.Run();
执行结果

image-1659778546926

由于这样写,代码不能复用 应该像Net6一样封装成对应的Middleware类 然后这边注入即可:

app.UseMiddleware<TestMiddleWare>();

中间件类

1、如果中间件的代码比较复杂,或者我们需要重复使用一个中间件的话,我们最好把中间件的代码放到一个单独的“中间件类”中。
2、中间件类是一个普通的.NET类,它不需要继承任何父类或者实现任何接口,但是这个类需要有一个构造方法,构造方法至少要有一个RequestDelegate类型的参数,这个参数用来指向下一个中间件。这个类还需要定义一个名字为Invoke或InvokeAsync的方法,方法至少有一个HttpContext类型的参数,方法的返回值必须是Task类型。中间件类的构造方法和Invoke(或InvokeAsync)方法还可以定义其他参数,其他参数的值会通过依赖注入自动赋值。

Program

using MiddleWare;

var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();

//此时只能处理localhost
app.MapGet("/", () => "Hello World!");
app.UseMiddleware<TestMiddleWare>();
//自定义中间件测试MiddleWare
//一般不在Use里面输出内容  只在Run里面做此操作 这段代码仅仅做演示 
//由于这样写,代码不能复用  应该向Net6一样封装成对应的Middleware类 然后这边注入即可
app.Map("/test", pilebuilder => {
//app.UseMiddleware<TestMiddleWare>(); 这个写在这里就只能对localhost/test的请求起作用
    pilebuilder.Use(async (context,next) =>
    {
        //以下代码为前代码
        context.Response.ContentType = "text/html;charset=UTF-8";
        await context.Response.WriteAsync("1 start<br/>");
        //以上代码为前代码
        await next.Invoke();
        //以下代码为后代码
        await context.Response.WriteAsync("1 end<br/>");
        //以上代码为后代码
    });
    pilebuilder.Use(async (context, next) =>
    {
        //以下代码为前代码
        await context.Response.WriteAsync("2 start<br/>");
        //以上代码为前代码
        await next.Invoke();
        //以下代码为后代码
        await context.Response.WriteAsync("2 end<br/>");
        //以上代码为后代码
    });
    pilebuilder.Run(async context =>
    {
        var pw = context.Items["content"];
        //端点(终点)中间件
        await context.Response.WriteAsync(pw+"+Hellp MiddleWare<br/>");
    });
});
app.Run();

TestMiddleWare:检查请求中是否有password=123的查询字符串,有的话把密码 123打出来

namespace MiddleWare
{
    public class TestMiddleWare
    {
        public RequestDelegate _next;
        public TestMiddleWare(RequestDelegate next )
        {
            _next=next;
        }

        public async Task InvokeAsync(HttpContext context)
        {
            var pw = context.Request.Query["password"];
            if (pw == "123")
            {
                context.Items["content"] = "密码 123";
                await _next(context);
            }
            else
            {
                context.Response.StatusCode = 401;
            }
        }

    }
}
执行结果

image-1659778575786

失败结果

image-1659778597874

总结:

以上就是中间件的基本概念和使用,中间件是Net6的核心组件,十分重要,是高级程序员所必要掌握的。求职面试中也是热点问题。

本文内容大部分都为杨中科老师《ASP.NET Core技术内幕与项目实战》一书中内容,此文只是做学习记录,如有侵权,联系立马删除。