.NET Core开发实战(第21课:中间件:掌控请求处理过程的关键)--学习笔记(下)...
21 | 中間件:掌控請求處理過程的關鍵
如果在 Map 的時候邏輯復雜一點,不僅僅判斷它的 URL 地址,而且要做特殊的判斷的話,可以這么做把判斷邏輯變成一個委托
我們要判斷當我們的請求地址包含 abc 的時候,輸出 new abc
app.MapWhen(context => {return context.Request.Query.Keys.Contains("abc"); }, builder => {builder.Run(async context =>{await context.Response.WriteAsync("new abc");}); });啟動程序,沒有任何輸出
當我們在默認啟動地址后面輸入 ?abc=1 的時候,可以看到輸出了 new abc
這里用到了一個 Run 的方法,上一節用到的是 Use 方法
app.Map("/abc", abcBuilder => {abcBuilder.Use(async (context, next) =>{//await context.Response.WriteAsync("Hello");await next();await context.Response.WriteAsync("Hello2");}); });Run 和 Use 的區別是什么呢?
Use 是指我們可以像注冊一個完整的中間件一樣,將 next 注入進來,我們可以去決定是否執行后續的中間件
Run 的含義就表示我們這里就是中間件執行的末端,也就不在執行后面的中間件了,在這里將返回請求
那我們如何像 UseRouting UseEndpoints 一樣來設計我們自己的中間件呢?
這里定義好了一個 MyMiddleware
namespace MiddlewareDemo.Middlewares {class MyMiddleware{RequestDelegate _next;ILogger _logger;public MyMiddleware(RequestDelegate next, ILogger<MyMiddleware> logger){_next = next;_logger = logger;}public async Task InvokeAsync(HttpContext context){using (_logger.BeginScope("TraceIdentifier:{TraceIdentifier}", context.TraceIdentifier)){_logger.LogDebug("開始執行");await _next(context);_logger.LogDebug("執行結束");}}} }定義中間件是用了一個約定的方式,中間件的類包含一個方法 Invoke 或者 InvokeAsync 這樣一個方法,它的返回是一個 Task,入參是一個 HttpContext,實際上可以理解成與中間件的委托是一樣的,只要我們的類包含這樣一個方法,就可以把它作為一個中間件注冊進去,并被框架識別到
這里還定義了一個 MyBuilderExtensions
namespace Microsoft.AspNetCore.Builder {public static class MyBuilderExtensions{public static IApplicationBuilder UseMyMiddleware(this IApplicationBuilder app){return app.UseMiddleware<MyMiddleware>();}} }把我們的中間件注冊進去,這個方法就是 UseMyMiddleware
通過這樣的定義,我們就可以使用自己的中間件
app.UseMyMiddleware();啟動程序,輸出如下:
控制臺輸出
dbug: MiddlewareDemo.Middlewares.MyMiddleware[0]=> RequestPath:/weatherforecast RequestId:0HLU50UEM3M9F:00000001, SpanId:|77f92fe8-4a6d800968327989., TraceId:77f92fe8-4a6d800968327989, ParentId: => TraceIdentifier:0HLU50UEM3M9F:00000001開始執行 dbug: MiddlewareDemo.Middlewares.MyMiddleware[0]=> RequestPath:/weatherforecast RequestId:0HLU50UEM3M9F:00000001, SpanId:|77f92fe8-4a6d800968327989., TraceId:77f92fe8-4a6d800968327989, ParentId: => TraceIdentifier:0HLU50UEM3M9F:00000001執行結束網頁控制器輸出
[{"date":"2020-03-11T23:30:55.3411696+08:00","temperatureC":20,"temperatureF":67,"summary":"Warm"},{"date":"2020-03-12T23:30:55.3417863+08:00","temperatureC":52,"temperatureF":125,"summary":"Bracing"},{"date":"2020-03-13T23:30:55.3417916+08:00","temperatureC":-3,"temperatureF":27,"summary":"Mild"},{"date":"2020-03-14T23:30:55.341792+08:00","temperatureC":35,"temperatureF":94,"summary":"Balmy"},{"date":"2020-03-15T23:30:55.3417923+08:00","temperatureC":37,"temperatureF":98,"summary":"Sweltering"}]Hello2如果要實現一個斷路器,就是不執行后續邏輯,注釋掉一行
_logger.LogDebug("開始執行");//await _next(context);_logger.LogDebug("執行結束");啟動程序,頁面不會輸出任何內容,只會在控制臺打印出中間件的執行過程,后續的控制器不會執行
這樣就實現了一個斷路器,也就意味著可以使用自己的中間件做請求的控制,而且時非常靈活的控制
在使用中間件的過程中,需要非常注意的是注冊中間件的順序,這些順序就決定了中間件執行的時機,某些中間件會是斷路器的作用,某些中間件會做一些請求內容的處理
還有一個比較關鍵的要點是指應用程序一旦開始向 Response write 的時候,后續的中間件就不能再去操作它的 header,這一點是需要注意的
可以通過 Context.Response.HasStarted 來判斷是否已經開始向響應的 body 輸出內容,一旦輸出了內容,就不要再操作 header
總結
以上是生活随笔為你收集整理的.NET Core开发实战(第21课:中间件:掌控请求处理过程的关键)--学习笔记(下)...的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 这些年我对微服务的理解
- 下一篇: 200行代码,7个对象——让你了解ASP