.NET Core基础篇之:白话管道中间件
在.Net Core中,管道往往伴随着请求一起出现。客户端发起Http请求,服务端去响应这个请求,之间的过程都在管道内进行。
举一个生活中比较常见的例子:旅游景区。
我们都知道,有些景区大门离景区很远,我们需要经过层层关卡才能到达景区。
我的请求最终就是去到景区,去到景区的整个过程就是管道,景区就是服务器,层层关卡就是一个个中间件了,比如:门票、停车费、摆渡费等等。
如果其中任何一个中间件卡壳了,比如我没买门票,那别人肯定是不让我进去,这就是管道短路了。
.NET Core 请求管道包含一系列Http请求委托(RequestDelegate),依次调用。
微软给的图示:

.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)
    {
    }
}

这也是.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");
});

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


从上面的例子中我们可以看到,中间件都是由上而下依次执行,由每个中间件决定是否继续执行下一个中间件,最终到响应结果。
如果哪个中间件决定不往下执行,那通道也就短路了,比如我们去掉 middleware2 的 await next.Invoke();
执行到 Console.WriteLine("middleware2 : out"); 就短路了,此路不通,原路返回。

因为管道中间件执行逻辑的关系,我们在实际开发中要注意两点:
- 1、谨慎使用管道短路 
- 2、注意中间件的使用顺序,比如:路由中间件肯定是要在认证中间件前面执行,有中间件需要访问文件,在此之前就必须先执行开放静态文件的中间件 
.NET Core基础篇之:白话管道中间件的更多相关文章
- Asp.Net Core基础篇之:白话管道中间件
		在Asp.Net Core中,管道往往伴随着请求一起出现.客户端发起Http请求,服务端去响应这个请求,之间的过程都在管道内进行. 举一个生活中比较常见的例子:旅游景区. 我们都知道,有些景区大门离景 ... 
- Core 1.0中的管道-中间件模式
		ASP.NET Core 1.0中的管道-中间件模式 SP.NET Core 1.0借鉴了Katana项目的管道设计(Pipeline).日志记录.用户认证.MVC等模块都以中间件(Middlewar ... 
- ASP.NET Core 1.0中的管道-中间件模式
		ASP.NET Core 1.0借鉴了Katana项目的管道设计(Pipeline).日志记录.用户认证.MVC等模块都以中间件(Middleware)的方式注册在管道中.显而易见这样的设计非常松耦合 ... 
- .NET Core基础篇之:配置文件读取
		配置文件是每个项目最基础的部分,也是不可或缺的部分,比如:数据库连接.中间件属性等常见的配置. 今天这篇文章主要内容就是,在.Net Core项目中怎样去读取配置文件并使用. 提前准备 appsett ... 
- .NET Core基础篇之:依赖注入DependencyInjection
		依赖注入已经不是什么新鲜话题了,在.NET Framework时期就已经出现了各种依赖注入框架,比如:autofac.unity等.只是在.net core微软将它搬上了台面,不用再依赖第三方组件(那 ... 
- .NET Core基础篇之:集成Swagger文档与自定义Swagger UI
		Swagger大家都不陌生,Swagger (OpenAPI) 是一个与编程语言无关的接口规范,用于描述项目中的 REST API.它的出现主要是节约了开发人员编写接口文档的时间,可以根据项目中的注释 ... 
- ASP.NET Core 基础知识(四) Startup.cs类
		ASP.NET Core应用程序需要一个启动类,按照约定命名为Startup.在 Program 类的主机生成器上调用 Build 时,将生成应用的主机, 通常通过在主机生成器上调用 WebHostB ... 
- 你所不知道的库存超限做法  服务器一般达到多少qps比较好[转]  JAVA格物致知基础篇:你所不知道的返回码  深入了解EntityFramework Core 2.1延迟加载(Lazy Loading)   EntityFramework 6.x和EntityFramework Core关系映射中导航属性必须是public?  藏在正则表达式里的陷阱  两道面试题,带你解析Java类加载机制
		你所不知道的库存超限做法 在互联网企业中,限购的做法,多种多样,有的别出心裁,有的因循守旧,但是种种做法皆想达到的目的,无外乎几种,商品卖的完,系统抗的住,库存不超限.虽然短短数语,却有着说不完,道不 ... 
- ASP.NET Core 中间件 - ASP.NET Core 基础教程 - 简单教程,简单编程
		原文:ASP.NET Core 中间件 - ASP.NET Core 基础教程 - 简单教程,简单编程 ASP.NET Core 中间件 上一章节中,我们我们有讲到 Startup 类中的 Confi ... 
随机推荐
- 花了30天才肝出来,史上最全面Java设计模式总结,看完再也不会忘
			本文所有内容均节选自<设计模式就该这样学> 序言 Design Patterns: Elements of Reusable Object-Oriented Software(以下简称&l ... 
- Pulsar云原生分布式消息和流平台v2.8.0
			Pulsar云原生分布式消息和流平台 **本人博客网站 **IT小神 www.itxiaoshen.com Pulsar官方网站 Apache Pulsar是一个云原生的分布式消息和流媒体平台,最初创 ... 
- 洛谷 P4755 - Beautiful Pair(主席树+分治+启发式优化)
			题面传送门 wssb,我紫菜 看到这类与最大值统计有关的问题可以很自然地想到分治,考虑对 \([l,r]\) 进行分治,求出对于所有 \(l\le x\le y\le r\) 的点对 \((x,y)\ ... 
- 51nod 1709 复杂度分析
			51nod 1709 复杂度分析 考虑定义 $ F(x) $ 为 \(x\) 为根的子树所有点与 $ x $ 的深度差(其实就是 $ x $ 到每个子树内点的距离)的 1 的个数和. 注意,$ F(x ... 
- 除了GO基因本体论,还有PO、TO、CO等各种Ontology?
			目录 PO/TO CO 后记 我们最常用最熟悉的功能数据库之一:GO(gene onotology),基因本体论.其实是一套标准词汇术语,目的是从不同角度来描述某个基因的特点和功能,三大本体如生物学进 ... 
- 字符scanf 的输入注意
			1.注意scanf 不能有空格,如果有空格会将空格给输入进去 scanf("d "):---有空格 和scanf("d");--没有空格 有很大的区别 
- 字符串String的trim()方法
			用来删除字符串两端的空白字符并返回,trim方法并不影响原来的字符串本身,它返回的是一个新的字符串 String a = " Hello World "; String b = ... 
- Hive(十)【窗口函数】
			目录 一.定义 窗口函数: 标准聚合函数 分析排名函数 二.语法 (1)窗口函数 over([partition by 字段] [order by 字段] [ 窗口语句]) (2)窗口语句 三.需求练 ... 
- JavaScript 链表
			------------恢复内容开始------------ 背景 数组并不总是组织数据的最佳数据结构,原因如下.在很多编程语言中,数组的长度是固定的,所以当数组已被数据填满时,再要加入新的元素就会非 ... 
- Oracle——概要文件profile
			profile文件详解 一.目的 Oracle系统中的profile可以用来对用户所能使用的数据库资源进行限制,使用Create Profile命令创建一个Profile,用它来实现对 ... 
