.net core 5.0 之自定义中间件
微软官方自定义中间件文档:https://docs.microsoft.com/zh-cn/aspnet/core/fundamentals/middleware/write?view=aspnetcore-5.0#per-request-middleware-dependencies
1. 中间件的定义:(官方文档) https://docs.microsoft.com/zh-cn/aspnet/core/fundamentals/middleware/?view=aspnetcore-5.0
中间件是一种装配到应用管道以处理请求和响应的软件。 每个组件:
a. 选择是否将请求传递到管道中的下一个组件。
b. 可在管道中的下一个组件前后执行工作。
请求委托用于生成请求管道。 请求委托处理每个 HTTP 请求。
使用 RunMap 和 Use 扩展方法来配置请求委托。 可将一个单独的请求委托并行指定为匿名方法(称为并行中间件),或在可重用的类中对其进行定义。 这些可重用的类和并行匿名方法即为中间件,也叫中间件组件。 请求管道中的每个中间件组件负责调用管道中的下一个组件,或使管道短路。 当中间件短路时,它被称为“终端中间件”,因为它阻止中间件进一步处理请求。
2. 管道中间件官方建议的执行顺序
3. 自定义中间件实现必须满足两点条件
3.1. 具有类型为 RequestDelegate 的参数的公共构造函数。
3.2. 名为 Invoke
或 InvokeAsync
的公共方法。 此方法必须:
a. 返回 Task
。
b. 接受类型 HttpContext 的第一个参数。
4. 实现示例
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | public class CustomMiddleware { public string _msg; public RequestDelegate _requestDelegate; public CustomMiddleware(RequestDelegate requestDelegate, string msg) { _requestDelegate = requestDelegate; _msg = msg; } public async Task InvokeAsync(HttpContext httpContext) { Console.WriteLine(_msg); await _requestDelegate(httpContext); } } |
1 2 3 4 5 6 7 | public static class MiddlewareExtension { public static IApplicationBuilder Custom( this IApplicationBuilder app, string msg) { return app.UseMiddleware<CustomMiddleware>(msg); } } |
startup更改:
1 | app.Custom( "hello" ); |
请求http://localhost:5000/之后的运行结果:
5. 扩展资料:
.net core 都是通过 IApplicationBuilder 来添加中间件创建管道,所以中间件都是围绕它来创建的。请求管道包含一系列请求委托,依次调用。每个委托均可在下一个委托前后执行操作。 应尽早在管道中调用异常处理委托,这样它们就能捕获在管道的后期阶段发生的异常。
配置请求委托的几种方式:
- app.Use(): 将多个请求委托链接在一起,按照顺序依次执行。
next
参数表示管道中的下一个委托。 可通过不调用 next 参数使管道短路。 通常可在下一个委托前后执行操作.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | public class Startup { public void Configure(IApplicationBuilder app) { app.Use(async (context, next) => { // Do work that doesn't write to the Response. await next.Invoke(); // Do logging or other work that doesn't write to the Response. }); app.Run(async context => { await context.Response.WriteAsync( "Hello from 2nd delegate." ); }); } } |
- app.Run():委托不会收到
next
参数。 第一个Run
委托始终为终端,用于终止管道。如果在Run
委托之后添加了另一个Use
或Run
委托,则不会调用该委托。
1 2 3 4 5 6 7 8 9 10 | public class Startup { public void Configure(IApplicationBuilder app) { app.Run(async context => { await context.Response.WriteAsync( "Hello from 2nd delegate." ); }); } } |
- app.map() : 用作约定来创建管道分支。
Map
基于给定请求路径的匹配项来创建请求管道分支。 如果请求路径以给定路径开头,则执行分支。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 | public class Startup { private static void HandleMapTest1(IApplicationBuilder app) { app.Run(async context => { await context.Response.WriteAsync( "Map Test 1" ); }); } private static void HandleMapTest2(IApplicationBuilder app) { app.Run(async context => { await context.Response.WriteAsync( "Map Test 2" ); }); } public void Configure(IApplicationBuilder app) { app.Map( "/map1" , HandleMapTest1); app.Map( "/map2" , HandleMapTest2); app.Run(async context => { await context.Response.WriteAsync( "Hello from non-Map delegate. <p>" ); }); } } |
下表使用前面的代码显示来自 http://localhost:1234
的请求和响应。
- app.MapWhen() : 基于给定前面的谓词的结果来创建请求管道分支。
MapWhen(this IApplicationBuilder app, Func<HttpContext, bool> predicate, Action<IApplicationBuilder> configuration)简单来说就是predicate如果为true则执行后面的configuration委托
- app.UseWhen() : 也基于给定谓词的结果创建请求管道分支。 与
MapWhen
不同的是,如果这个分支不发生短路或包含终端中间件,则会重新加入主管道。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 全程不用写代码,我用AI程序员写了一个飞机大战
· DeepSeek 开源周回顾「GitHub 热点速览」
· 记一次.NET内存居高不下排查解决与启示
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!