1. 程式人生 > 其它 >Asp.NetCore 自定義中介軟體

Asp.NetCore 自定義中介軟體

這節演示一下自定義中介軟體,第一節我們講到,中介軟體的處理流程就像一個俄羅斯套娃,那這種俄羅斯套娃型的流程內部是如何實現的呢,下面請看程式碼​。

​第一種寫法是直接寫在Configure方法中的,使用app.Use(委託)配合lambda表示式使用,適合很輕量級的中介軟體。​

app.Use(async (context, next) =>
  {
      await context.Response.WriteAsync("CustomerMiddleWare1-in\n");
      await next();
      await context.Response.WriteAsync("CustomerMiddleWare1-out");
  });

​微軟約定中介軟體需要兩個引數,一個是httpcontext上下文物件,一個是Task型別的委託​。通過上下文物件,處理請求,通過委託​傳遞上下文物件到下一個中介軟體(這也是套娃模式的由來)。

​這也限制了方法,必須是非同步的async方法,呼叫next()之後,上下文物件傳送給下一中介軟體了,該方法就會處於等待狀態,直到後續的中介軟體處理完畢,返回後,再執行next()方法之後的程式碼​。(關於同步和非同步的有關知識,將在後續進行講解)

​除了使用Use()方法,還有一種用法,這個方法有點特殊,因為它不存在next()方法傳遞上下文物件,它是請求管道的底,用於直接返回響應

//run 是終端中介軟體,他是沒有next()方法的,只要進入這個中介軟體,後續的中介軟體都不會執行了,從它這裡請求完畢原路返回 
 app.Run(async context =>
 {
      await context.Response.WriteAsync("I am End MiddleWare\n");
 });

​.NetCore3.x推出了一個新的中介軟體,叫EndPoints

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

​它跟Run()一樣,是兜底的中介軟體,但是用法比較特殊了,微軟給我們的預設配置就是直接路由到某一頁面,一般是網站首頁​。

下面看一下執行結果的演示,有如下三個中介軟體:

 //use是新增中間中介軟體,就是處理完了,繼續傳給下一個中介軟體,它有next()委託
 app.Use(async (context, next) =>
 {
   await context.Response.WriteAsync("CustomerMiddleWare1-in\n");
   await next();
   await context.Response.WriteAsync("CustomerMiddleWare1-out");
 });
 app.Use(async (context, next) =>
 {
   await context.Response.WriteAsync("CustomerMiddleWare2-in\n");
   await next();
   await context.Response.WriteAsync("CustomerMiddleWare2-out\n");
 });
//run 是終端中介軟體,他是沒有next()方法的,只要進入這個中介軟體,後續的中介軟體都不會執行了,從它這裡請求完畢原路返回 
 app.Run(async context =>
 {
   await context.Response.WriteAsync("I am End MiddleWare\n");
 });

執行結果為:

這很直觀的反應了中介軟體的順序執行,以及巢狀執行

下面看一下如何定義一個真正的自定義中介軟體

首先,我們要明確,微軟規定的自定義中介軟體的要求

1.具有型別為RequestDelegate引數的公共建構函式,這個引數就是請求委託,它在一個個的中介軟體中傳遞

2.具有Invoke或者InvokeAsync的方法,該方法的返回值必須是Task,而且第一個引數必須是HttpContext

 public class MyMiddleWare
    {
        private readonly RequestDelegate _next;

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

        public async Task InvokeAsync(HttpContext context)
        {
            //此處寫中介軟體業務邏輯
            //然後呼叫next指向下一個中介軟體
            //呼叫next之前,屬於請求部分的處理
            await _next(context);
            //next執行完畢之後,屬於相應部分的處理
        }
    }

​定義完成以後,使用UseMiddleware<中介軟體>()將自定義中介軟體新增進來

app.UseMiddleware<MyMiddleWare>();

​但這樣的用法,還是少了一點優雅與靈活性,我們可以通過擴充套件方法的形式,為IApplicationBuilder新增擴充套件方法,實現自定義中介軟體新增與配置的靈活應用(擴充套件方法在之前的文章中有講)​

public static class MyMiddleWareExtension
    {
        public static IApplicationBuilder UseMymiddleware(this IApplicationBuilder app)
        {
            return app.UseMiddleware<MyMiddleWare>();
        }
    }

這樣的話,就可以直接呼叫方法新增中介軟體了

 //使用擴充套件方法的形式,新增自定義中介軟體然後可以通過構造方法的形式,傳遞配置引數
 app.UseMymiddleware();

初學者可對此做初步瞭解,對其中設計的程式碼語法知識,是必須要掌握的。另外,如果需要檢視ASP.NetCore的原始碼,請訪問https://github.com/dotnet/aspnetcore自行下載或克隆到本地

 這是我公眾號二維碼,最新的文章會同步至此