.NET CORE 中介軟體
阿新 • • 發佈:2020-06-04
## 什麼是中介軟體 ##
對於中介軟體我們其實並不陌生,在.NET CORE出現之前中介軟體的概念在OWIN應用程式中就已經普遍使用了。
中介軟體官方定義: 中介軟體是一種整合到應用管道中間來處理請求和響應的模組,每個中介軟體可以:
- 選擇是否將請求傳遞到管道的下一個元件
- 可以在管道的下一個元件前後執行工作
ASP.NETCORE中的中介軟體本質上是一個請求委託 `Func< RequestDelegate, RequestDelegate> middleware`。
RequestDelegate本身也是一個委託,定義為 `public delegate Task RequestDelegate(HttpContext Context)`。
在ASP.NETCORE請求管道中,形成一條委託鏈。
![委託鏈](https://img2020.cnblogs.com/blog/365548/202006/365548-20200604105209232-842964941.png)
請求管道短路:當委託不選擇將請求傳遞到下一個委託時,稱之為“短路”。
## 如何建立中介軟體 ##
在ASP.NETCORE中,使用 `IApplicationBuilder` 來建立/插入中介軟體管道。提供了 **Run**和**Use** 兩類方式。依賴元件包 `Microsoft.AspNetCore.Http.Abstractions`
Run是一種 **約定** 的終端管道,即短路,不再執行下一個委託
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
app.Run(async context => { await context.Response.WriteAsync("hello world 1"); });
//這裡不會執行到!!
app.Run(async context => { await context.Response.WriteAsync("hello world 2"); });
}
Use通常以擴充套件方法提供中介軟體,很適合處理一些AOP的事務。
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
app.Use(async (context, next) =>
{
//可以在invoke之前做一些事
await next.Invoke();
//可以在invoke之後做一些事
});
app.Run(async context => { await context.Response.WriteAsync("hello world"); });
}
實際開發中我們通常需要自己定義中介軟體,有兩種方式可以實現。
### 約定方式 ###
public class RequestIdInRequestMiddleware
{
private readonly RequestDelegate _next;
public RequestIdInRequestMiddleware(RequestDelegate next)
{
_next = next;
}
public Task Invoke(HttpContext httpContext,IService service)
{
service.SayHello();
//request head 加入requestid
var requestId = Guid.NewGuid().ToString("n");
httpContext.Request.Headers.Add("REQUESTID", requestId);
return _next(httpContext);
}
}
如上有以下約定:
- 具有型別為 `RequestDelegate` 的引數公共建構函式
- 名為 `Invoke` 或 `InvokeAsync` 的公共方法,且此方法必須:
- 返回 `Task`
- 第一個引數為 `HttpContext`
目前官方是推薦使用約定方式, **注意**:該方式加入管道中的生命週期為**單例**。也因此如果依賴一些Service,建議從`Invoke` 或 `InvokeAsync`的方法引數注入,而不是從建構函式注入。(可以想想為什麼?單例建構函式注入對Service的生命週期有要求~~)。
### 強型別 ###
官方也提供了IMiddleware介面,用於擴充套件建立中介軟體。這種方式有兩個優點:
- 可以按需(生命週期)注入
- 中介軟體強型別話,更易理解
public class RequestIdInResponseMiddleware:IMiddleware
{
private readonly IService _service;
public RequestIdInResponseMiddleware(IService service)
{
_service = service;
}
public Task InvokeAsync(HttpContext context, RequestDelegate next)
{
var requestId = Guid.NewGuid().ToString("n");
context.Response.Headers.Add("REQUESTID", requestId);
return next(context);
}
}
### 中介軟體加入管道 ###
中介軟體一般都是基於IApplicationBuilder擴充套件方法加入管道。
public static class RequestIdMiddlewareExtensions
{
public static IApplicationBuilder UseRequestIdInResponseMiddleware(this IApplicationBuilder builder)
{
return builder.UseMiddleware