写点什么

浅聊一下中间件

作者:为自己带盐
  • 2022 年 7 月 04 日
  • 本文字数:2146 字

    阅读完需:约 7 分钟

浅聊一下中间件

先浅聊一下基本概念

其实关于中间件,它也不是什么神秘的东西。咱们既然定位在了浅聊(主要是深了咱也不会),就单独拿出几个典型的应用场景来聊一下。注意咱这都是小场面,可不是那个广义的中间件,只是在 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>(); }}
复制代码

运行之后,呈现的效果就是这样

好了,大概就是这样,聊的比较浅,中间件具体实例也只是简单打印了一点文字,实际是要写日志,还是做监控还是干什么的,就根据实际的业务需求去调整就好了。

晚安啦~

发布于: 刚刚阅读数: 6
用户头像

学着码代码,学着码人生。 2019.04.11 加入

狂奔的小码农

评论

发布
暂无评论
浅聊一下中间件_中间件_为自己带盐_InfoQ写作社区