.NET Core基础篇之:白话管道中间件

在.Net Core中,管道往往伴随着请求一起出现。客户端发起Http请求,服务端去响应这个请求,之间的过程都在管道内进行。

举一个生活中比较常见的例子:旅游景区

我们都知道,有些景区大门离景区很远,我们需要经过层层关卡才能到达景区。

我的请求最终就是去到景区,去到景区的整个过程就是管道,景区就是服务器,层层关卡就是一个个中间件了,比如:门票、停车费、摆渡费等等。

如果其中任何一个中间件卡壳了,比如我没买门票,那别人肯定是不让我进去,这就是管道短路了。

.NET Core 请求管道包含一系列Http请求委托(RequestDelegate),依次调用。

微软给的图示:

image

.Net Core服务

在解释管道的使用方法之前,我们先来准备一个.Net Core服务。

创建一个.Net Core控制台应用程序,并实现如下代码,一个简单的使用 Kestrel 托管的服务就完成了:

internal class Program { static void Main(string[] args) { new WebHostBuilder() .UseKestrel() .UseStartup<Startup2>() .Build() .Start(); Console.ReadLine(); } } public class Startup { public void Configure(IApplicationBuilder app) { } }

image

这也是.Net Core的优点之一,只选择我们需要的,摒弃那些多余的功能。优点是优点,一般开发中也犯不上这样去做。

Kestrel 托管默认监听端口:5000

管道中间件

微软这边内置了三个扩展函数供我们构建自己的中间件:

Use

Map

Run

其中Use和Map函数还提供了对应的分支扩展:UseWhen、MapWhen、UseMiddleware。下面我们一个个来解释。

app.Use

Use 是最常用的一种模式,承接上一个请求并执行下一个请求的任务

public void Configure(IApplicationBuilder app) { app.Use(async (context, next) => { Console.WriteLine("middleware1"); await next.Invoke(); }); app.Use(async (context, next) => { Console.WriteLine("middleware2"); }); } app.UseWhen

UseWhen在Use的基础上提供了条件分支的功能

app.UseWhen(context => // 判断请求路径的开头是否是/h context.Request.Path.StartsWithSegments(new PathString("/h")), c => c.Use(async (context, next) => { Console.WriteLine("middleware1"); await next.Invoke(); }) ); app.Use(async (context, next) => { Console.WriteLine("middleware2"); });

image

app.Map

Map我们可以理解成专为请求路径扩展的分支中间件,可以根据请求路径去处理对应分支逻辑,与上面的UseWhen例子效果类似,但更加方便。

app.Map("/h", _app => { _app.Use(async (context, next) => { Console.WriteLine("hello world"); }); }); app.MapWhen

MapWhen与UseWhen类似,都是在请求上下文的基础上去扩展分支,比Map更加灵活。

app.MapWhen(context => { return context.Request.Query["name"] == "tony"; }, _app => { _app.Use(async (context, next) => { context.Response.ContentType = "text/plain; charset=utf-8"; await context.Response.WriteAsync("i 服了 you"); }); }); app.Run

Run一般用于断路或请求管道的末尾,不会将请求传递下去

app.Run(async context => { await context.Response.WriteAsync("hello world"); }); UseMiddleware

将一个完整的类添加到管道中间件,也就是将上面的请求委托,用类以及函数的形式替代了,便于我们的代码管理。

app.UseMiddleware<DotnetboyMiddleware>(); public class DotnetboyMiddleware { private readonly RequestDelegate _next; private readonly string _name; public DotnetboyMiddleware(RequestDelegate next, string name) { _next = next; _name = name; } public Task Invoke(HttpContext context) { context.Response.WriteAsync($"my name is {_name}").Wait(); return this._next(context); } }

微软内置的一些管道中间件扩展函数就介绍完了,下面我们实现一下微软实例图示中的效果:

public void Configure(IApplicationBuilder app) { app.Use(async (context, next) => { Console.WriteLine("middleware1 : in"); await next.Invoke(); Console.WriteLine("middleware1 : out"); }); app.Use(async (context, next) => { Console.WriteLine("middleware2 : in"); await next.Invoke(); Console.WriteLine("middleware2 : out"); }); app.Run(async context => { Console.WriteLine("Hello World"); await context.Response.WriteAsync("Hello World"); }); }

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/zzyypy.html