.NET Core技術研究-中間件的由來和使用

我們將原有ASP.NET應用升級到ASP.NET Core的過程中,會遇到一個新的概念: 中間件。

中間件是ASP.NET Core全新引入的概念。 中間件是一種裝配到應用管道中以處理請求和響應的軟件。 每個組件:

  • 選擇是否將請求傳遞到管道中的下一個組件。
  • 可在管道中的下一個組件前後執行工作。

單獨看以上中間件的定義,一個很直觀的感覺:中間件是HTTP請求管道中的一層層的AOP擴展。

在展開介紹中間件之前,我們先回顧一下ASP.NET中HttpHandler和HttpModule的處理方式。

一、ASP.NET中HttpHandler和HttpModule

先看一張圖:

.NET Core技術研究-中間件的由來和使用

上圖中有兩個概念HttpHandler和HttpModule,其中:

HttpHandler 用於處理具有給定文件名或擴展名的請求。比如上圖中的.report類的請求,同時,任何一個HttpHandler都需要實現接口IHttpHandler,都需要在Web.Config配置文件中註冊使用。

HttpModule 用於處理每個請求調用,比如上圖中的Authorization Module,每個Http請求都會經過HttpModule的處理。通過HttpModule可以中斷Http請求,可以自定義HttpResponse返回。同時,任何一個HttpModule都需要實現接口IHttpModule,都需要在Web.Config配置文件中註冊使用。

ASP.NET Core引入了中間件來實現上面2種Http請求處理擴展。ASP.NET Core中間件和 ASP.NET HttpHandler HttpModule有什麼區別?

二、ASP.NET Core中間件和 ASP.NET HttpHandler HttpModule的區別

1. 中間件比HttpHandler、HttpModule更簡單

  • "模塊"、"處理程序"、" Global.asax.cs "、 "WEB.CONFIG" (IIS 配置除外)和 "應用程序生命週期" 消失
  • 中間件已使用HttpHandler HttpModule的角色
  • 中間件使用代碼而不 是在 web.config 中進行配置
  • 通過管道分支,可以將請求發送到特定的中間件,不僅可以基於 URL,還可以發送到請求標頭、查詢字符串等。

2. 中間件類似於HttpModule

  • 處理每個請求調用
  • 可以實現Http請求中間和繼續
  • 能夠創建自定義的HttpResponse

3. 中間件和HttpModule按不同的順序處理

  • 中間件的順序取決於它們插入請求管道的順序,而模塊的順序主要基於應用程序生命週期事件
  • 中間件中Http響應的順序與Http請求的順序相反,而對於HttpModule,請求和響應的順序是相同的。
.NET Core技術研究-中間件的由來和使用

、ASP.NET Core中間件的設計原理

ASP.NET Core 請求管道包含一系列請求委託,依次調用。 下圖演示了這一概念。 沿黑色箭頭執行。

.NET Core技術研究-中間件的由來和使用

每個請求委託(中間件)都可以在下一個請求委託(中間件)之前和之後執行操作。中間件中的 異常處理委託應該在管道的早期被處理,這樣就可以捕獲在管道後期發生的異常。

在Startup.Configure 方法中添加中間件組件的順序定義了針對請求調用這些中間件的順序,以及響應的相反順序。 這個順序對於安全性、性能和功能非常重要。

看一段示例代碼:

<code>public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
app.UseDatabaseErrorPage();
}
else
{
app.UseExceptionHandler("/Error");
app.UseHsts();
}

app.UseHttpsRedirection();
app.UseStaticFiles();
// app.UseCookiePolicy();

app.UseRouting();
// app.UseRequestLocalization();
// app.UseCors();

app.UseAuthentication();
app.UseAuthorization();
// app.UseSession();

app.UseEndpoints(endpoints =>
{
endpoints.MapRazorPages();
endpoints.MapControllerRoute(
name: "default",
pattern: "{controller=Home}/{action=Index}/{id?}");
});
}/<code>

上述代碼中每個中間件擴展方法都通過 Microsoft.AspNetCore.Builder 命名空間在 IApplicationBuilder 上公開。

app.Use***都是各種常用的內置中間件。比如:

1. 異常處理類中間件。如上述代碼中:

當應用在開發環境中運行時:異常顯示頁中間件 (UseDeveloperExceptionPage) 報告應用運行時錯誤。數據庫錯誤頁中間件報告數據庫運行時錯誤。(app.UseDatabaseErrorPage();)

當應用在生產環境中運行時:異常處理程序中間件 (UseExceptionHandler) 捕獲以下中間件中引發的異常。TTP 嚴格傳輸安全協議 (HSTS) 中間件 (UseHsts) 添加 Strict-Transport-Security 標頭。

2. HTTPS 重定向中間件 (UseHttpsRedirection) 將 HTTP 請求重定向到 HTTPS。

3. 靜態文件中間件 (UseStaticFiles) 返回靜態文件,並簡化進一步請求處理。

4. Cookie 策略中間件 (UseCookiePolicy) 使應用符合歐盟一般數據保護條例 (GDPR) 規定。

5. 用於路由請求的路由中間件 (UseRouting)。

6. 身份驗證中間件 (UseAuthentication) 嘗試對用戶進行身份驗證,然後才會允許用戶訪問安全資源。

7. 用於授權用戶訪問安全資源的授權中間件 (UseAuthorization)。

8. 會話中間件 (UseSession) 建立和維護會話狀態。 如果應用使用會話狀態,請在 Cookie 策略中間件之後和 MVC 中間件之前調用會話中間件。

9. 用於將 Razor Pages 終結點添加到請求管道的終結點路由中間件(帶有 MapRazorPages 的 UseEndpoints)。

10. 對於單頁應用程序 (SPA),SPA 中間件 UseSpaStaticFiles 通常是中間件管道中的最後一個。 SPA 中間件處於最後的作用是:允許所有其他中間件首先響應匹配的請求。允許具有客戶端側路由的 SPA 針對服務器應用無法識別的所有路由運行。

還有很多其他的內置中間件,可以參考鏈接: https://docs.microsoft.com/en-us/aspnet/core/fundamentals/middleware/?view=aspnetcore-3.0 。如下圖,

.NET Core技術研究-中間件的由來和使用

瞭解了ASP.NET Core內置的中間件之後,我們可能需要自定義一些中間件,比如說原有的ASP.NET HttpModule和HttpHandler.

接下來第四部分,我們繼續示例:

、自定義中間件

將已有HttpModule用自定義中間件實現

先看一下原有HttpModule的一個實現:

<code>/// <summary>
/// 自定義HTTP擴展模塊
/// /<summary>
public class CustomerHttpModule : IHttpModule
{
public void Init(HttpApplication context)
{
context.BeginRequest += Context_BeginRequest;
}

private void Context_BeginRequest(object sender, EventArgs e)
{
HttpApplication app = (HttpApplication)sender;
// Do something
}

public void Dispose()
{

}
}/<code>

遷移到中間件實現:

<code>/// <summary>
/// 自定義中間件
/// /<summary>
public class CustomerMiddleware
{
private readonly RequestDelegate _next;

public CustomerMiddleware(RequestDelegate next)
{
_next = next;
}

public async Task Invoke(HttpContext context)
{
// Do something with context near the beginning of request processing.
await _next.Invoke(context);
// Clean up.
}
}/<code>

同時增加IApplicationBuilder的一個擴展方法:

<code>public static IApplicationBuilder UseCustomerMiddleware(this IApplicationBuilder builder)
{
return builder.UseMiddleware<customermiddleware>();
}/<customermiddleware>/<code>

Startup中使用這個中間件:

<code>app.UseCustomerMiddlewares();  /<code>

以上是對ASP.NET Core中中間件的技術由來整理和使用分享。


分享到:


相關文章: