Asp.net core中间件实现原理及用法解说
简述asp.net core中间件的实现思路
原文地址:https://www.cnblogs.com/shengyu-kmust/p/11583974.html
一次http请求的过程,就是对一个Request请求进行若干次逻辑处理,并最终设置Response的过程。从代码的实现维度看,由于Request和Response都在HttpContext里,可将此过程表示为“以一个httpContext为输入的委托函数”,即delegate Task RequestDelegate(HttpContext context),为方便此文的描述,我们将此委托函数暂时称为“请求处理逻辑”

而中间件的作用,就是在请求的后面加入一个处理逻辑,这个处理逻辑是以“前一个请求处理逻辑”为输入,并经过中间件自己的处理后,返回一个“新的请求处理逻辑”。所以从代码上可将“中间件”表式为以一个“请求处理逻辑”为输入并返回另一个“请求处理逻辑”的委托,即Func<RequestDelegate,RequestDelegate>。而多个中间件即表示为List<Func<RequestDelegate,RequestDelegate>>。

Asp.net core中间件的核心功能就是如何将一系列的中间件,合并成一个“请求处理逻辑”的过程,即如何将List<Func<RequestDelegate,RequestDelegate>>合并生成一个RequestDelegate。合并逻辑如下


上面的代码有两个地方要注意
1、asp.net core会默认在请求的最后加入一个“404”处理的中间件。
2、合并时,组件是先反序后再循环的
因先加入的中间件要先执行,所以在合并时,第一个中间件要最后合并,即要倒序后再循环合并中间件
如何使用中间件
使用中间件有四种方法:Use、Run、Map和使用Middleware class,但前三种方法最终调用的都是Use方法,我们来看看Use方法的实现逻辑,如下

即use方法只是在中间件列表(_components)的最后再加入一个中间件
下面详细描述四种方法的用法
Use的用法
Ues的用法有两种
用法一
调用IApplicationBuilder Use(Func<RequestDelegate, RequestDelegate> middleware),此用法需在middleware委托里自己控制是否要进入下一个中间件,并且要自己创建一个RequestDelegate并返回,写法会比较复杂。
示例如下

用法二
调用IApplicationBuilder Use(this IApplicationBuilder app, Func<HttpContext, Func<Task>, Task> middleware),这是一个扩展方法,此方法不用自己创建RequestDelegate并返回,写法比较简洁。它最终调用的方法还是用法一中的实现,此方法的实现代码如下。

示例如下

需注意:上面的两种Use用法,在第二个中间件时,并没有再调用下一个中间件,这是为了确保http请求不会进入到asp.net core默认的最后一个404中间件,因为最后一个404中间件设置了status code,而一但response body之前已经开始写入时,是不能再改变status code或是request header的,否则会报错。微软的官方文档里要求中间件的使用要遵循如下规则:如response body改变后就不要再调用下一个中间件,避免下一个中间件对上一个中间件的httpcontext内容的污染。(本文示例为演示目的,未遵循此约定)

run的用法
run方法的实现代码如下


注意:从run方法的实现的代码可以看出,run是不会再执行下一个中间件的,所以第一个中间run方法后面的中间件都不会起作用。所以一般用run时都是放在中间件的最后
map的用法
map其实准确来说不是中间件的用法,而是新开一个“中间件请求路线分支”,在这个“分支”里,可以再用use和run方法来组件一个新的中间件逻辑。
示例如下

如上示例,请求地址当能匹配上/test里,才会启用map里的中间件
Middleware class的用法
Middleware class不需要继承任何类或是接口,但必须有名为Invoke,返回类型为Task,且第一个参数为HttpContext类型的方法。
示例如下


Asp.net core内置中间件的介绍
|
中间件名称 |
如何使用及说明 |
|
Authentication |
App.UseAuthentication,验证当前请求的用户,并设置HttpContext.User,当OAuth callbacks时,会中止执行下一个中间件。放到要用到用户验证的中间件前面 |
|
Static File |
app.UseStaticFiles(),判断当前请求是否为静态文件,如果是则中止执行下一个中间件,否则继续下一个中间件。放到管道的最前 |
|
Response Caching |
app.UseResponseCaching(),缓存中间件 |
|
MVC |
app.UseMvc(),将MVC引入到中间件管道,如果请求的地址能找到对应的MVC路由,则中止执行下一个中间件。放到管道的最后。 |
|
Exception |
app.UseDeveloperExceptionPage();或app.UseExceptionHandler();用于处理程序的异常信息。放到管道的最前 |
|
Authorization |
授权中间件。不需直接引用,App.UseMvc()会在内部调用,并配合app.UseAuthentication()一起使用。 |
中间件的总结
1、通过use,run,map,middleware class四种方法使用
2、使用多个中间件时,需注意中间件的顺序
3、在设计中间件时,请遵循“责任分离”原则,即一个中间件只对“单一责任”进行处理,如验证用户、授权等。
4、如果对response body做了修改后,请不要再执行下一个中间件
Asp.net core中间件实现原理及用法解说的更多相关文章
- asp.net core中间件工作原理
不少刚学习.net core朋友对中间件的概念一直分不清楚,到底StartUp下的Configure方法是在做什么? public void Configure(IApplicationBuilder ...
- ASP.NET Core 中间件基本用法
ASP.NET Core 中间件 ASP.NET Core的处理流程是一个管道,而中间件是装配到管道中的用于处理请求和响应的组件.中间件按照装配的先后顺序执行,并决定是否进入下一个组件.中间件管道的处 ...
- ASP.NET Core中间件实现分布式 Session
1. ASP.NET Core中间件详解 1.1. 中间件原理 1.1.1. 什么是中间件 1.1.2. 中间件执行过程 1.1.3. 中间件的配置 1.2. 依赖注入中间件 1.3. Cookies ...
- 【ASP.NET Core】运行原理之启动WebHost
ASP.NET Core运行原理之启动WebHost 本节将分析WebHost.CreateDefaultBuilder(args).UseStartup<Startup>().Build ...
- 【ASP.NET Core】运行原理(2):启动WebHost
本系列将分析ASP.NET Core运行原理 [ASP.NET Core]运行原理[1]:创建WebHost [ASP.NET Core]运行原理[2]:启动WebHost [ASP.NET Core ...
- 【ASP.NET Core】运行原理(1):创建WebHost
本系列将分析ASP.NET Core运行原理 [ASP.NET Core]运行原理[1]:创建WebHost [ASP.NET Core]运行原理[2]:启动WebHost [ASP.NET Core ...
- ASP.NET Core中间件实现分布式 Session(转载)
ASP.NET Core中间件实现分布式 Session 1. ASP.NET Core中间件详解 1.1. 中间件原理 1.1.1. 什么是中间件 1.1.2. 中间件执行过程 1.1.3. 中间件 ...
- ASP.NET Core 中间件自定义全局异常处理
目录 背景 ASP.NET Core过滤器(Filter) ASP.NET Core 中间件(Middleware) 自定义全局异常处理 .Net Core中使用ExceptionFilter .Ne ...
- ASP.NET Core 中间件Diagnostics使用
ASP.NET Core 中间件(Middleware)Diagnostics使用.对于中间件的介绍可以查看之前的文章ASP.NET Core 开发-中间件(Middleware). Diagnost ...
随机推荐
- Nginx配置信息损毁又无备份时如何恢复
worker_processes *; 本文介绍在Nginx配置信息出现问题后,在没有备份的情况下,如何利用Nginx进程的虚拟内存恢复配置信息. 问题背景 假设 /etc/nginx/site-av ...
- hwclock和date源码分析
一. hwclock 1.1 hwclock源码在哪里? util-linux 或者busybox 1.2 获取源码 git clone https://github.com/karelzak/uti ...
- <JavaScript>几道javascript练习题
问题1: 作用域(Scope) 考虑以下代码: (function() { var a = b = 5; })(); console.log(b); 控制台(console)会打印出什么? 答案 上述 ...
- R-CNN论文学习
Rich feature hierarchies for accurate object detection and semantic segmentation Tech report (v5) pr ...
- Spring Boot使用监听器Listener
之前介绍了在Spring Boot中使用过滤器:https://www.cnblogs.com/zifeiy/p/9911056.html 接下来介绍使用监听器Listener. 下面是一个例子: p ...
- MODRD 指令 读取地址是哪儿来的
MODRD s1 s2 n 例如: MODRD K1 H2102 K2 (台达VFDM变频器) 读取变频器的主频率及输出频率,并存放于寄存器D1050,D1051指令中s2的数据地址是 ...
- 简单的api实现以及动态函数调用
实现一个简单的api功能,环境python2.7 请求方法:curl http://ip:8000/?name={api中的方法名}|python -m json.tool 只需编写api的方法即可 ...
- 如何提高程序员的键盘使用效率?——ASE第一次作业
引言 对于程序员来说,键盘输入是我们工作的基本方式,当你的手指在键盘上飞起来的时候,不但能够提高工作效率,还常常引来旁人羡慕的目光.下面将从不同方面介绍一些提高键盘使用效率的方法. 程序员最主要的文字 ...
- 网络损伤仪细分市场:eCPRI网络损伤的技术要求
关于“网络损伤仪”的叫法 网络损伤仪,也称作为广域网仿真仪,广域网损伤仪,WAN Emulation,Network Impairment Emulator. 为什么会带WAN广域网这个限定词? 应该 ...
- vue告警信息:{ parser: "babylon" } is deprecated.
告警信息: 13% building modules 28/40 modules 12 active ...dex=0!\src\App.vue{ parser: "babylon" ...