ASP.NET Core 中間件 中間件(Middleware)和過濾器(Filter)的區別


http://www.javashuo.com/article/p-xshwgqda-bb.htmlhtml


前言

上篇文章主要介紹了DotNetCore項目情況,本篇文章是咱們在開發本身的項目中實際使用的,比較貼合實際應用,算是對中間件的一個深刻使用了,不是簡單的Hello World,若是你以爲本篇文章對你有用的話,不妨點個【推薦】。web

目錄
  • 中間件(Middleware)的做用
  • 中間件的運行方式
  • 中間件(Middleware)和過濾器(Filter)的區別
  • 什麼狀況咱們須要中間件
  • 怎麼樣自定義本身的中間件
中間件(Middleware)的做用

咱們知道,任何的一個web框架都是把http請求封裝成一個管道,每一次的請求都是通過管道的一系列操做,最終到達咱們寫的代碼中。那麼中間件就是在應用程序管道中的一個組件,用來攔截請求過程進行一些其餘處理和響應。中間件能夠有不少個,每個中間件均可以對管道中的請求進行攔截,它能夠決定是否將請求轉移給下一個中間件。app

asp.net core 提供了IApplicationBuilder接口來讓把中間件註冊到asp.net的管道請求當中去,中間件是一個典型的AOP應用。 下面是一個微軟官方的一箇中間件管道請求圖:框架

image

能夠看到,每個中間件都均可以在請求以前和以後進行操做。請求處理完成以後傳遞給下一個請求。asp.net

中間件的運行方式

默認狀況下,中間件的執行順序根據Startup.cs文件中,在public void Configure(IApplicationBuilder app){} 方法中註冊的前後順序執行。
大概有3種方式能夠在管道中註冊"中間件"ui

  1. app.Use()IApplicationBuilder接口原生提供,註冊等都用它。
  2. app.Run() ,是一個擴展方法,它須要一個RequestDelegate委託,裏面包含了Http的上下文信息,沒有next參數,由於它老是在管道最後一步執行。
  3. app.Map(),也是一個擴展方法,相似於MVC的路由,用途通常是一些特殊請求路徑的處理。如:www.example.com/token 等。

上面的Run,Map內部也是調用的Use,算是對IApplicationBuilder接口擴充,若是你以爲名字都不夠準確,那麼下面這個擴展方法就是正宗的註冊中間件的了,也是功能最強大的。
app.UseMiddleware<>(),沒錯,就是這個了。 爲何說功能強大呢?是由於它不但提供了註冊中間件的功能,還提供了依賴注入(DI)的功能,之後大部分狀況就用它了。this

中間件(Middleware)和過濾器(Filter)的區別

熟悉MVC框架的同窗應該知道,MVC也提供了5大過濾器供咱們用來處理請求先後須要執行的代碼。分別是AuthenticationFilter,AuthorizationFilter,ActionFilter,ExceptionFilter,ResultFilter.net

根據描述,能夠看出中間件和過濾器的功能相似,那麼他們有什麼區別?爲何又要搞一箇中間件呢?
其實,過濾器和中間件他們的關注點是不同的,也就是說職責不同,乾的事情就不同。日誌

舉個栗子,中間件像是埃辛諾斯戰刃,過濾器像是巨龍之怒,泰蕾苟薩的寄魂杖 ,你一個戰士拿着巨龍之怒,泰蕾苟薩的寄魂杖去戰場殺人,雖然都有傷害,可是你拿着法杖傷害低不說,還減屬性啊。code

同做爲兩個AOP利器,過濾器更貼合業務,它關注於應用程序自己,好比你看ActionFilterResultFilter,它都直接和你的Action,ActionResult交互了,是否是離你很近的感受,那我有一些好比對個人輸出結果進行格式化啦,對個人請求的ViewModel進行數據驗證啦,確定就是用Filter無疑了。它是MVC的一部分,它能夠攔截到你Action上下文的一些信息,而中間件是沒有這個能力的。

什麼狀況咱們須要中間件

那麼,什麼時候使用中間件呢?個人理解是在咱們的應用程序當中和業務關係不大的一些須要在管道中作的事情可使用,好比身份驗證,Session存儲,日誌記錄等。其實咱們的 asp.net core項目中自己已經包含了不少箇中間件。

舉例,咱們在新建一個 asp.net core應用程序的時候,默認生成的模板當中

public void Configure(IApplicationBuilder app, ILoggerFactory loggerFactory)
{
    app.UseDeveloperExceptionPage();
    
    app.UseStaticFiles();
    
    loggerFactory.AddConsole();
    
    app.UseMvc(routes =>
    {
        routes.MapRoute(
            name: "default",
            template: "{controller=Home}/{action=Index}/{id?}");
    });
}

懶得去下載源碼了,咱們使用Reflector去查看源碼:

//擴展方法`app.UseDeveloperExceptionPage();`
public static class DeveloperExceptionPageExtensions
{
    // Methods
    public static IApplicationBuilder UseDeveloperExceptionPage(this IApplicationBuilder app)
    {
        if (app == null)
        {
            throw new ArgumentNullException("app");
        }
        return UseMiddlewareExtensions.UseMiddleware<DeveloperExceptionPageMiddleware>(app, Array.Empty<object>());
    }
}
//擴展方法`app.UseStaticFiles();`
public static class StaticFileExtensions
{
   // Methods
   public static IApplicationBuilder UseStaticFiles(this IApplicationBuilder app)
    {
        if (app == null)
        {
            throw new ArgumentNullException("app");
        }
        return UseMiddlewareExtensions.UseMiddleware<StaticFileMiddleware>(app, Array.Empty<object>());
    }
}

能夠看到 app.UseDeveloperExceptionPage()app.UseStaticFiles()等等都是經過中間件實現的。

相關文章
相關標籤/搜索