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

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

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

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

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


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

微软给的图示:

.Net Core服务

在解释管道的使用方法之前,我们先来准备一个Asp.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) { }}

 

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

Kestrel 托管默认监听端口:5000

管道中间件

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

  1. Use

  2. Map

  3. Run

其中UseMap函数还提供了对应的分支扩展:UseWhenMapWhenUseMiddleware。下面我们一个个来解释。

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

UseWhenUse的基础上提供了条件分支的功能


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");});

 

app.Map

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


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

app.MapWhen

MapWhenUseWhen类似,都是在请求上下文的基础上去扩展分支,比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");    });}

从上面的例子中我们可以看到,中间件都是由上而下依次执行,由每个中间件决定是否继续执行下一个中间件,最终到响应结果。

如果哪个中间件决定不往下执行,那通道也就短路了,比如我们去掉 middleware2 的 await next.Invoke();

执行到 Console.WriteLine("middleware2 : out"); 就短路了,此路不通,原路返回。

因为管道中间件执行逻辑的关系,我们在实际开发中要注意两点:

  • 1、谨慎使用管道短路

  • 2、注意中间件的使用顺序,比如:路由中间件肯定是要在认证中间件前面执行,有中间件需要访问文件,在此之前就必须先执行开放静态文件的中间件

最新文章

  1. [转]http-关于application/x-www-form-urlencoded等字符编码的解释说明
  2. win 8 安装 NET framework3.5 方法
  3. arduino 串口实时绘图(以mpu9250为例)
  4. Android中关于Volley的使用(五)从RequestQueue开始来深入认识Volley
  5. pip高级使用技巧以及搭建自己的pypi服务器
  6. BZOJ 1054 题解
  7. MVC学习中遇到问题
  8. Nginx下用webbench进行压力测试
  9. [pdf.js]预览pdf时,中文名称乱码的问题
  10. 推荐一个非常COOL的开源相册程序!
  11. Java多线程-新特征-锁(上)
  12. C#学习笔记四: C#3.0自动属性&amp;匿名属性及扩展方法
  13. 关于 MySQL 的 boolean 和 tinyint(1) (转)
  14. SkinPP for VC
  15. Pomodairo,番茄工作法-应用篇
  16. component object model(组件对象模型)
  17. 磁盘IO性能监控(Linux 和 Windows)
  18. JSON 串 自定义解析字段
  19. 在 HTML5 中捕获音频和视频
  20. 当使用xmapp时session序列化生成的文件的路径

热门文章

  1. Linux安装KingbaseES数据库 Unsupported major.minor version错误处理
  2. React Refs-知识点整理记录
  3. drf-视图集、路由系统、action装饰器
  4. 2211-12 Hello Flask!
  5. 4.12 疫情数据可视化 毕设(初稿版 crud+可视化echarts
  6. 运行第一个Go文件
  7. 【多线程与高并发】- synchronized锁的认知
  8. 基于pytorch实现模型剪枝
  9. T-SQL——将字符串转为单列
  10. Prometheus插件安装(NodeExporter)