- Java锁的逻辑(结合对象头和ObjectMonitor)
- 还在用饼状图?来瞧瞧这些炫酷的百分比可视化新图形(附代码实现)⛵
- 自动注册实体类到EntityFrameworkCore上下文,并适配ABP及ABPVNext
- 基于Sklearn机器学习代码实战
请求管道是什么?请求管道描述的是一个请求进到我们的后端应用,后端应用如何处理的过程,从接收到请求,之后请求怎么流转,经过哪些处理,最后怎么返回响应。请求管道就是一次请求在后端应用的生命周期。了解请求管道,有助于我们明白后端应用是怎么工作的,我们的代码是怎么工作的,在我们的业务代码执行前后经过哪些步骤,有助于我们之后更好的实现一些AOP操作.
请求管道是 .net 应用的一个最基本的概念。在 .net core 中,微软对框架底层进行了全新的设计,相对于原本的ASP.NET中的全家桶模式的管道模型,.net core的管道模型更加灵活便捷,可做到热插拔,通过管道可以随意注册自己想要的服务或者第三方服务插件,这也是.net core性能更好的原因.
以上是微软官方文档中的管道模型图。从图中可以看到 服务器接收到请求之后,将接收到的请求向后传递,依次经过一个个 Middleware 进行处理,然后由最后一个 MiddleWare 生成响应内容并回传,再反向依次经过每一个 Middleware,直到由服务器发送出去。整个过程就像一条流水线一样,管道这个词是很形象的,而 Middleware 就像一层一层的“滤网”,过滤所有的请求和响应.
管道之中,对请求、响应进行加工处理的模块是 Middleware ,也就是中间件。中间件本质上是一个委托.
从上面的图可以看出,每一个中间件都会被执行两次,在下一个中间件执行之前和之后各执行一次,分别是在处理请求和处理响应,只有一个中间件是例外的,那就是最后一个中间件,它后面没有下一个中间件,所以执行到它管道就会回转.
这代表了中间件的两种工作模式,也是中间件的两种基本注册方式。中间件本质上是一个委托,在代码实现上就体现在委托的入参有所不同以及注册调用的方法不同.
中间件两种最基本的注册方式:
在代码中分别是以下方式:
app.Use(async (context, next) =>
{
await context.Response.WriteAsync("Hello Middlerware !");
if(context.Request.Query.TryGetValue("query", out var query))
{
await context.Response.WriteAsync(query);
}
await next();
await context.Response.WriteAsync("End Middleware !");
});
app.Run(async context =>
{
await context.Response.WriteAsync("Hello last Middleware");
});
最后的执行结果如下,也可以从代码执行的先后顺序看出管道流动的顺序。当前中间件手动调用 next() 之后,就进入下一个中间件,下一个中间件处理完成之后,按照管道的顺序再一个一个回传。在这个过程中一直不变,被管道传递的就是HttpContext,而我们拿到 HttpContext,即可以通过 Request 和 Response 对当前这一次的请求做任何处理了.
通过分析asp.net core的源码,可以看到在我们调用 Run() 的时候,实际上还是调用了 Use() 方法.
而 Use() 方法中,主要的逻辑仅仅只是将相应的委托存放到集合中 。
之后在 build 方法调用的时候才一个一个地调用中间件委托.
除了上面的 Use() 、Run() 两个最基本的方法注册中间件之外,还有另外一些方法,如通过 Map() 方法注册中间件,这种方式会创建一个新的管道分支,在路由满足Map的规则时,请求则转型新的管道分支,最后沿着管道分支返回响应,而不走原有的管道.
app.Use(async (context, next) =>
{
await context.Response.WriteAsync("Hello Middlerware1 ! ");
if(context.Request.Query.TryGetValue("query", out var query))
{
await context.Response.WriteAsync(query);
}
await next();
await context.Response.WriteAsync("End Middleware1 ! ");
});
app.Map("/map", app =>
{
// map方法中的委托,传入的时IApplicationBuilder, 在这里相当于一个新的管道,也可以和主管道一样进行任意操作
app.Run(async context =>
{
await context.Response.WriteAsync("Hello map Middleware pipeline ! ");
});
});
app.Run(async context =>
{
await context.Response.WriteAsync("Hello last Middleware ! ");
});
执行结果如下:
其他的分支管道创建方式,如 MapWhen,和 Map 大同小异,只是对于匹配判断的方式有所不同。像微软内置中间件中的静态文件中间件,MVC 中间件,其实都是以分支管道的方式实现的,一旦匹配到请求就会走管道分支.
使用一个中间件需要在 .net core 的入口文件中进行配置,如果是 .net 6版本,那只要在 program.cs 文件中进行配置即可,通过 WebApplication 对象,也就是 app 调用相关的方法.
如果是 .net 6 以下版本,可以在 startup.cs 文件中的 Configure 方法中配置。.net 6 与之前版本入口文件的不同上一篇文章也讲过,这里就不赘述了.
这里可以看得到,一些中间件的调用并没有直接使用 Use() 和 Run(),毕竟将各个中间件的处理逻辑全部放在入口文件很不好管理,而且也很不优雅。这里涉及到了中间件封装的约定规则,一般情况下封装一个中间件都会提供一个 Use[Middleware] 方法以供使用者进行中间件的调用,WebApplication 对象的 UseXXX 方法都是中间件调用的方法.
ASP.NET Core 框架之中内置有很多中间件,并且我们通过 VS 创建某一个类型的项目时,如MVC、Razor Page,初始化的项目代码中会帮我们配置好一些中间件.
以上为官方文档中列出的内置中间件,可以看到在列表中对每个中间件的顺序进行了说明.
管道中的中间件排列是有先后之分的,请求和响应按照中间件的排列顺序进行传递,这也是我们代码逻辑执行的顺序,而且一些中间件需要依赖于其他中间件的处理结果,或者必须在某些中间件前先执行,否则就会出问题了.
而中间件插入到管道中的顺序,就是依据我们在入口文件中调用相应中间注册方法的顺序,所以代码的前后顺序非常重要,一旦写错了就会出现很多意想不到的的Bug.
向 Program.cs 文件中添加中间件组件的顺序定义了针对请求调用这些组件的顺序,以及响应的相反顺序。 此顺序对于安全性、性能和功能至关重要。这是官方文档中的原话.
官方文档给出了典型MVC应用的管道中间件顺序,这里其实不止MVC,Razor Page、Web Api 也是这样的管道模型,如下图。这里也明确了我们自定义的中间件应该插入到哪个位置.
更多的内置中间件的作用,以及相应的管道顺序要求,请详细阅读一下官方文档,这里就不细说了.
参考文章:
ASP.NET Core 中间件 。
ASP.NET Core 系列: 目录: ASP.NET Core 系列总结 上一篇: ASP.NET Core - .NET 6 的入口文件 。
最后此篇关于ASP.NETCore-请求管道与中间件的文章就讲到这里了,如果你想了解更多关于ASP.NETCore-请求管道与中间件的内容请搜索CFSDN的文章或继续浏览相关文章,希望大家以后支持我的博客! 。
有人可以给我一个更简单的以下代码的解决方案(它正在展开给定结构 0xFC :: len :: payload :: ... :: 0x0A :: 0x0D 的整数列表): object Payload
我已经在我的网站上安装了 SSL 证书,但 intermediate.crt 无法正常工作。任何 SSL 检查器(例如 GeoTrust Checker)都告诉我,缺少中间 key 。网站上已经使用了
如何让图像从这个框的中间开始? (中间纵横) 最佳答案 有几种方法可以做到这一点,如果它需要在所有浏览器(IE7+ 和其他浏览器)中工作,你需要做不同的事情来让它在某些情况下工作。 使用绝对位置
如何强制 min-height 和 vertical-align:middle 为 td 元素或其内部元素工作? 最佳答案 td 元素上的 height 等同于 min-height,因为如果需要,表
我正在尝试自动滚动到订单簿的中间行。 我有 orderBook div,其中放置了带有 orderBook 的表。该表的其中一行有一个 id middleRow。我想做的是滚动该行并将其放置在 ord
我正在尝试在 javascript 中计算绝对定位元素的 transform-origin 属性,以便它们在悬停时填充整个视口(viewport)。 我尝试通过 x 除以窗口宽度和 y 除以窗口高度来
我有休闲字符串 ' this is my string ' 是否可以删除开头和结尾的所有空格,只在单词之间留一个空格。 要选择我使用过的所有空间: SELECT regexp_replace('
我正在设法创建我的第一个复杂的 J2E 解决方案,并且在每个教程中我都发现了某种中间表的用法,如下所示: 表:用户、用户角色、角色虽然逻辑会简单地向用户表添加一个键来引用它在角色表上的角色,但为什么要
我正在寻找以下解决方案。我想定位一个图像元素,例如 在中间。所以高度是视口(viewport)的高度,宽度会自动设置,图像的中间应该在视口(viewport)宽度的中间。 我搜索的一个例子就像下面的网
我正在设计一种布局,它更像是注册用户的个人仪表板。我让它变得简单,使用基本的 2 列网格,一个用于侧边栏,一个用于主要内容。 因为,例如,80% 的网站使用将发生在一个单独的子系统中,在无 chrom
我有三个不同的 div 标签(不在彼此内部)和代码,所以它有一个把单词放在左边、中间或右边,但中心非常偏离中心。这是 HTML 代码: .desc { float: right; color:
我有以下CSS http://jsbin.com/azivip/75/edit我想让黄色的 div 高度填充蓝色和绿色 div 之间的空间。使用高度继承似乎使 div 超出了绿色 div。 有什么想法
我不得不在其父元素的中间放置一些文本。我用下面的代码实现了它: #div1 { position: relative; margin: 0; padding: 0; } #div2 {
发现一个使用合法证书(由thawte 签名)的网站,但所有浏览器都会拒绝它。我不明白为什么。thawte 的支持告诉我一个域有两个证书,然后将这个 https://www.sslshopper[dot
我正在尝试使用 OpenSSL 创建证书链,但出于某种原因,当我在我的计算机上安装我的根 CA 并尝试验证证书链时,它总是告诉我它找不到证书的颁发者.为了让事情发生,我必须安装中间 CA,这是没有意义
我看到 REST 的一大好处是依赖 HTTP 缓存。我不是在争论这个,而是完全认同这个想法。但是,我从来没有看到对中间 HTTP 缓存的更深入的解释。 如果我将 Cache-control heade
查看此图片 Facebook Messenger Android App Buttons ( MESSENGER\ACTIVE ) 我怎样才能做到这一点? 详细信息:- 带有 2px 红色边框的 di
我的任务是制作漂亮的文本,在文本中间加一条白线,如下图所示。是否可以使用 css 来实现?这是 Fiddle .container{ height:200px; width:400px;
在拉丁文字中,字母有大写和小写形式。在 Python 中,如果你想比较两个字符串而不考虑它们的大小写,你可以使用 'string'.upper() 或 'string'.lower() 将它们转换为相
我正在使用 awk 对文件进行一些文本处理。例如删除尾随空格。 awk '{gsub(/ +$/, "")} {print $0}' filename 这很好用。但是当我将输出重定向到原始文件时。它变
我是一名优秀的程序员,十分优秀!