4.4管道Middleware簡介「深入淺出ASP.NET Core系列」
希望給你3-5分鐘的碎片化學習,可能是坐地鐵、等公交,積少成多,水滴石穿,謝謝關注。
管道流
瞭解管道流機制,就能知道如何利用管道進行攔截,自定義封裝等高階操作,所以學習管道流機制對我們編碼有質的提高。那麼管道資料是如何流通的呢?如下圖所示,Request進入管道Middleware 1,疊加一層邏輯程式碼到HttpContext(切確說是HttpContext的Response物件),然後呼叫next()進入到下一個管道Middleware 2,依次遞推,最後所有的邏輯程式碼疊加完畢後返回前端。
管道實踐
實現自定義管道有兩種方法,使用IApplicationBuilder的Use和Run方法,他們的區別在下面會談到。
app.Use方法
這裡先了解Use方法的第一個過載,如下圖所示,他是一個型別為委託的中介軟體(middleware)。
這個中介軟體同時攜帶一個next的RequestDelegate委託,可以實現呼叫下一個管道中介軟體,我們看下程式碼實踐,如下所示,context從當前管道進來,處理後,通過next.Invoke()轉移到下一個管道,完成一個管道的生命週期。
其實我更喜歡截圖,因為可以任意打標註,但是不方便拷貝,所以一起貼上程式碼吧。
app.Use(async (context, next) => { await context.Response.WriteAsync("fisrt……"); await next.Invoke(); });
以上的用法,如果是新手可能不知其所以然,用沒問題,但是內部是如何實現的?不知道!其實這裡使用到了語言的高階特性委託,通過委託實現了開閉原則,也就是把管道的擴充套件開放出來,我們可以使用規定的app.Use方法,但是內部定義的委託引數型別,比如context,Fun<task>則對外遮蔽了實現。所以你看到的next.Invoke()已經封裝了具體的實現了,對於使用者,其實可以不用去管那麼多,拿來用即可。
app.Use還有另外一個過載,如下圖提示:這裡Func傳入一個RequestDelegate,返回一個RequestDelegate。不同於第一個過載,他沒有next.Invoke()的呼叫,而是之間返回一個RequestDelegate給app進行處理。
我們看下程式碼實現,外層紅色框是傳入的管道,內部綠色框是返回的管道。
app.Run
app.Run和app.Use不同之處在於,app.Use可以呼叫下一個中介軟體的管道,app.Run不會,我們演示一段程式碼。
app.Use(async (context, next) => { await context.Response.WriteAsync("<html><body>"); await context.Response.WriteAsync("<div>Inside middleware defined using app.Use</div>"); await next(); await context.Response.WriteAsync("</body></html>"); }); app.Run(async context => { await context.Response.WriteAsync("<div>Inside middleware defined using app.Run</div>"); });
//該管道會不會被列印呢? app.Use(async (context, next) => { await context.Response.WriteAsync("<html><body>"); await context.Response.WriteAsync("<div>Another Middleware defined using app.Use</div>"); await next(); await context.Response.WriteAsync("</body></html>"); });
如下圖所示,我們看到Run後面定義的第二個Use沒有打印出來,這是因為Run不會呼叫隨後的管道導致的,所以我們一般習管性把Run方法放在所有管道的最後。
希望以上分享對你有幫助,我是張飛洪,入行10年有餘,人不堪其憂,吾不改其樂,謝謝您關注我的頭條