先浅聊一下基本概念
其实关于中间件,它也不是什么神秘的东西。咱们既然定位在了浅聊(主要是深了咱也不会),就单独拿出几个典型的应用场景来聊一下。注意咱这都是小场面,可不是那个广义的中间件,只是在 dotnetcore 系统框架里的中间件。
我感觉中间件,就是把整个网络请求过程中的那些系统不应该管,或者管理起来很麻烦的部分,单独拎出去,交给中间件去做统一的处理。
再说的通俗一点就是,我们开发的系统,应该是以业务为中心,为实际的业务需求服务的。而如果系统中有过多的代码用来处理与业务不想干的东西,就会大幅提高系统代码的复杂度,造成后续业务的扩展非常麻烦。上面提到的那些“于业务不相干”的东西,大体包含了一下几个方面,日志,授权,验签,流量控制等等。
没错,中间件就是为了解决这些事情而出现的。
再浅看一个实际案例
在 DotnetCore 项目里,定义中间件非常方便,还是以之前那篇《》里的项目为案例,现在来定义一个中间件,来看一下运行效果(这里的案例我有参考桂素伟老师写的一些案例,推荐大家看一下桂老师的文章)。
首先,创建一个类文件,随便写几行代码,注意其中的RequestDelegate是一种委托类型,微软官方文档中也给出了解释,这个类,就是专门为处理 http 请求而诞生的,没有它,框架也就失去了对 HTTP 请求的处理能力。
public class TestMiddleware1
{
private readonly RequestDelegate _next;
public TestMiddleware1(RequestDelegate next)
{
_next = next;
}
public async Task InvokeAsync(HttpContext context)
{
AnsiConsole.MarkupLine($"[red]我是第1个中间件,我过来了-{DateTime.Now}[/]");
await _next(context);
AnsiConsole.MarkupLine($"[red]我是第1个中间件,我退下了-{DateTime.Now}[/]");
}
}
复制代码
之后,我们在定义一个静态的扩展类来调用管道的处理方法
public static class TestMiddlewareExtensions
{
public static void UseTest(this WebApplication app)
{
app.UseMiddleware<TestMiddleware1>();
}
}
复制代码
最后,就可以在主函数(Program.cs 或者 StartUp.cs)中调用中间件了
var app = builder.Build();
...其他中间件
app.UseTest();
复制代码
看下运行效果。
到这里,中间件就已经开始工作了。
定义中间件,还可以直接通过表达式的形式来定义,直接在主函数中编写即可,不过这样可能会造成代码不够清晰,但在一些特殊情况这样做还是有一定必要的。
代码如下
var app = builder.Build();
app.UseTest();
app.Use(async (context, next) =>
{
AnsiConsole.MarkupLine($"[Yellow]我是第2个中间件,我来自入口文件,我过来了-{DateTime.Now}[/]");
await next(context);
AnsiConsole.MarkupLine($"[Yellow]我是第2个中间件,我来自入口文件,我退下了-{DateTime.Now}[/]");
});
复制代码
运行效果如下
可以看到,中间件的执行顺序是有区别的,先注册的中间件,最后返回 Response,这一点在实际使用的时
候要注意,顺序不要搞错了,尤其是那些需要做一些特殊的业务处理的中间件。关于这一点,可以参见微软的官方文档。
然后,还是回到第一种定义中间件的方式。当我们需要定义多个中间件函数时,还是应该尽可能的把中间件单拎到独立的文件中,这样代码会更加清晰。第一个例子,如果注册多个中间件,就可以这样做
public class TestMiddleware1
{
private readonly RequestDelegate _next;
public TestMiddleware1(RequestDelegate next)
{
_next = next;
}
public async Task InvokeAsync(HttpContext context)
{
AnsiConsole.MarkupLine($"[red]我是第1个中间件,我过来了-{DateTime.Now}[/]");
await _next(context);
AnsiConsole.MarkupLine($"[red]我是第1个中间件,我退下了-{DateTime.Now}[/]");
}
}
public class TestMiddleware2
{
private readonly RequestDelegate _next;
public TestMiddleware2(RequestDelegate next)
{
_next = next;
}
public async Task InvokeAsync(HttpContext context)
{
AnsiConsole.MarkupLine($"[green]我是第2个中间件,我过来了-{DateTime.Now}[/]");
await _next(context);
AnsiConsole.MarkupLine($"[green]我是第2个中间件,我退下了-{DateTime.Now}[/]");
}
}
public class TestMiddleware3
{
private readonly RequestDelegate _next;
public TestMiddleware3(RequestDelegate next)
{
_next = next;
}
public async Task InvokeAsync(HttpContext context)
{
AnsiConsole.MarkupLine($"[blue]我是第3个中间件,我过来了-{DateTime.Now}[/]");
await _next(context);
AnsiConsole.MarkupLine($"[blue]我是第3个中间件,我退下了-{DateTime.Now}[/]");
}
}
public static class TestMiddlewareExtensions
{
public static void UseTest(this WebApplication app)
{
app.UseMiddleware<TestMiddleware1>();
app.UseMiddleware<TestMiddleware2>();
app.UseMiddleware<TestMiddleware3>();
}
}
复制代码
运行之后,呈现的效果就是这样
好了,大概就是这样,聊的比较浅,中间件具体实例也只是简单打印了一点文字,实际是要写日志,还是做监控还是干什么的,就根据实际的业务需求去调整就好了。
晚安啦~
评论