Netcore——Middleware中间件(1)
一、什么是中间件
比如流水线工作 每个工人做的事情都很唯一 ,如果要真正生产出一个手机,要经过每一个工人的处理才能得到一个完整的手机。如果上一个工人对手机做了,一些修改 那么这个修改也会保留到下一个工人手中,工人之间共享的是这部手机。
ASP.NET Core的处理流程是一个管道,而中间件是装配到管道中的用于处理请求和响应的组件。中间件按照装配的先后顺序执行,并决定是否进入下一个组件。中间件管道的处理流程如下图。
二、中间件连接器
Use、Map,Run方法常用来一起构建 HTTP Pipeline 管道。这几个方法把不同的中间件委托连接起来。
1.Use
该方法将会执行一个委托,然后将 交接棒
传给Pipeline的下一个中间件,因该方法短暂拥有 交接棒
,所以该方法可用于 短路操作
// 向应用程序的请求管道中添加一个Func委托,这个委托其实就是所谓的中间件。
// context参数是HttpContext,表示HTTP请求的上下文对象
// next参数表示管道中的下一个中间件委托,如果不调用next,则会使管道短路
// 用Use可以将多个中间件链接在一起
public class Startup
{
public void Configure(IApplicationBuilder app)
{
app.Use(async (context, next) =>
{
await context.Response.WriteAsync("进入第一个委托 执行下一个委托之前\r\n");
//调用管道中的下一个委托
await next.Invoke();
await context.Response.WriteAsync("结束第一个委托 执行下一个委托之后\r\n");
});
app.Run(async context =>
{
await context.Response.WriteAsync("进入第二个委托\r\n");
await context.Response.WriteAsync("Hello from 2nd delegate.\r\n");
await context.Response.WriteAsync("结束第二个委托\r\n");
});
}
}
2.Run
Run()方法中只有一个RequestDelegate委托类型的参数,没有Next参数,所以Run()方法也叫终端中间件,不会将请求传递给下一个中间件,也就是发生了“短路”。看下面的代码:
// Run方法向应用程序的请求管道中添加一个RequestDelegate委托
// 放在管道最后面,终端中间件
app.Run(handler: async context =>
{
await context.Response.WriteAsync(text: "Hello World1\r\n");
});
app.Run(handler: async context =>
{
await context.Response.WriteAsync(text: "Hello World2\r\n");
});
3.Map
Map作为惯例,将管道分流。Map根据给定请求路径匹配将请求管道分流。如果请求路径以指定路径开始,则执行分支。
public class Startup
{
private static void HandleMapTest1(IApplicationBuilder app)
{
app.Run(async context =>
{
await context.Response.WriteAsync("Map Test 1");
});
}
private static void HandleMapTest2(IApplicationBuilder app)
{
app.Run(async context =>
{
await context.Response.WriteAsync("Map Test 2");
});
}
public void Configure(IApplicationBuilder app)
{
app.Map("/map1", HandleMapTest1);
app.Map("/map2", HandleMapTest2);
app.Run(async context =>
{
await context.Response.WriteAsync("Hello from non-Map delegate. <p>");
});
}
}
三、自定义中间件
1. 基于约定的方式
定义一个Middleware的类。
public class RequestCultureMiddleware
{
private readonly RequestDelegate _next;
public RequestCultureMiddleware(RequestDelegate next)
{
_next = next;
}
public async Task InvokeAsync(HttpContext context)
{
var cultureQuery = context.Request.Query["culture"];
if (!string.IsNullOrWhiteSpace(cultureQuery))
{
var culture = new CultureInfo(cultureQuery);
CultureInfo.CurrentCulture = culture;
CultureInfo.CurrentUICulture = culture;
}
await _next(context);
}
}
编写完成之后,需要手动的将类注册到管道中才能生效,注册方式如下所示。
app.UseMiddleware<RequestCultureMiddleware>();
2.实现IMiddleware的方式
实现IMiddleware接口。
public class RequestCultureOtherMiddleware:IMiddleware
{
public async Task InvokeAsync(HttpContext context, RequestDelegate next)
{
var cultureQuery = context.Request.Query["culture"];
if (!string.IsNullOrWhiteSpace(cultureQuery))
{
var culture = new CultureInfo(cultureQuery);
CultureInfo.CurrentCulture = culture;
CultureInfo.CurrentUICulture = culture;
}
await next(context);
}
}
手动将中间件注册到容器中。
services.AddSingleton<IMiddleware,RequestCultureOtherMiddleware>();
注册到管道中
app.UseMiddleware<RequestCultureOtherMiddleware>();