前言
對中間件的一個概況,在《重新整理.net core 計1400篇》系列后面會深入。
正文
什么是中間件呢?
其實中間件這個概念來源於分布式,當然這是一個狹隘的概念了,現在中間件概念就非常廣泛了。
官網給出了這樣一張圖,這張圖認為從請求到響應過程中間都是中間件,包括我們認為的路由。
看一段node代碼:
var http = require("http");
http.createServer(function(req,res){
res.writeHead(200,{"Content-type":"text/blain"});
res.write("Hello NodeJs");
res.end();
}).listen(8888);
沒有學過node 也是ok的,從字面意思就是創建了一個http服務,然后端口是8888。
createServer 可以傳入一個方法,中間有兩個參數,一個參數是req,另一個參數就是res。
其實就是這么回事,我們寫的就是這個這個方法里面的代碼,至於,你想拿到req的什么參數,或者給res寫入什么信息,這些都是中間件的范疇。
那么問題來了,問什么叫做中間件呢?從語文的層面上理解,那就是分開的,一件一件的。
把這件要執行的這些封裝成一個一個模塊,那么這些模塊,這些可以通過調用next執行下一個模塊,同樣,如果不調用,那么中間件模塊就會中斷,因為有時候真的需要中斷,比如說權限中間件,
檢查到權限不符合直接返回讓其跳轉到權限頁面,剩下的模塊也用不到。
用 Use 將多個請求委托鏈接在一起。 next 參數表示管道中的下一個委托。 可通過不調用 next 參數使管道短路。
當委托不將請求傳遞給下一個委托時,它被稱為“讓請求管道短路”。 通常需要短路,因為這樣可以避免不必要的工作。
下圖為asp .net core 中默認的中間件順序,當然可以自己修改,但是這是一種推薦做法。
挺合理的一個東西,一開始就填入了異常處理機制。
然后是強制https 轉換->重定向->靜態資源文件->路由->是否跨域->認證->授權->我們自己自定義需求的。
因為這個endpoint 是不建議我們修改的,當然我們可以修改源碼中,畢竟開源了,but not must。
官網中同樣給了我們這個endpoint 做了什么,其實就是官方自己封裝了一些中間件。
當然我們也可以進行對endpoint自我的調整,因為可能使用不同的模板引擎:
app.UseEndpoints(endpoints =>
{
endpoints.MapRazorPages();
endpoints.MapControllerRoute(
name: "default",
pattern: "{controller=Home}/{action=Index}/{id?}");
});
從上面得到一個推薦的中間件注冊來看,認證和授權在靜態文件之后,那么我們知道我們的資源時需要授權來保護的。
那么如何保護靜態資源呢?這后面會有專門的一章實踐一下,看下是什么原理。
好的,那么看一下我們如何自定義中間件吧,也就是實踐一下下面這種圖。
Middleware1
public class Middleware1
{
public readonly RequestDelegate _next;
public Middleware1(RequestDelegate next)
{
_next = next;
}
public async Task Invoke(HttpContext context)
{
Console.WriteLine("Middleware1");
await _next(context);
await context.Response.WriteAsync("Middleware1");
}
}
public class Middleware2
{
public readonly RequestDelegate _next;
public Middleware2(RequestDelegate next)
{
_next = next;
}
public async Task Invoke(HttpContext context)
{
Console.WriteLine("Middleware2");
await _next(context);
await context.Response.WriteAsync("Middleware2");
}
}
Middleware3
public class Middleware3
{
public readonly RequestDelegate _next;
public Middleware3(RequestDelegate next)
{
_next = next;
}
public async Task Invoke(HttpContext context)
{
Console.WriteLine("Middleware3");
await _next(context);
await context.Response.WriteAsync("Middleware3");
}
}
擴展方法:
public static class Middleware1MiddlewareExtensions
{
public static IApplicationBuilder UserMiddleware1(this IApplicationBuilder builder)
{
return builder.UseMiddleware<Middleware1>();
}
public static IApplicationBuilder UserMiddleware2(this IApplicationBuilder builder)
{
return builder.UseMiddleware<Middleware2>();
}
public static IApplicationBuilder UserMiddleware3(this IApplicationBuilder builder)
{
return builder.UseMiddleware<Middleware3>();
}
}
加入中間件隊列:
app.UserMiddleware1();
app.UserMiddleware2();
app.UserMiddleware3();
request 順序
response 順序
這其實就是一種職責鏈模式,每個中間件確定是否該需求是否要下一級處理,同樣會產生一個處理回調。