## 官方说明
中间件是一种装配到应用管道以处理请求和响应的软件。 每个组件:
- 选择是否将请求传递到管道中的下一个组件。
- 可在管道中的下一个组件前后执行工作。
请求委托用于生成请求管道。 请求委托处理每个 HTTP 请求。
使用 RunMap 和 Use 扩展方法来配置请求委托。 可将一个单独的请求委托并行指定为匿名方法(称为并行中间件),或在可重用的类中对其进行定义。 这些可重用的类和并行匿名方法即为中间件 ,也叫中间件组件 。 请求管道中的每个中间件组件负责调用管道中的下一个组件,或使管道短路。 当中间件短路时,它被称为“终端中间件” ,因为它阻止中间件进一步处理请求。
## 执行顺序示例图
## 实测一下
++新建dotnet core 3.1 web 项目++
在 ==Startup== 的 ==Configure== 中
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
app.Use(async (context, next) =>
{
Stopwatch stopWatch = new Stopwatch();
stopWatch.Start();
await context.Response.WriteAsync("Middleware 1 Start \n");
await next.Invoke();
await context.Response.WriteAsync("Middleware 1 End \n");
stopWatch.Stop();
Console.WriteLine($"响应:{stopWatch.ElapsedMilliseconds}");
});
app.Use(async (context, next) =>
{
await context.Response.WriteAsync("Middleware 2 Start \n");
await next.Invoke();
await context.Response.WriteAsync("Middleware 2 End \n");
});
app.Use(async (context, next) =>
{
await context.Response.WriteAsync("Middleware 2 Start \n");
await next.Invoke();
await context.Response.WriteAsync("Middleware 2 End \n");
});
app.UseRouting();
app.UseEndpoints(endpoints =>
{
endpoints.MapGet("/", async context =>
{
await context.Response.WriteAsync("Hello World! \n");
});
endpoints.MapControllerRoute(
name: "default",
pattern: "{controller=Home}/{action=Index}/{id?}");
});
app.Use(async (context, next) =>
{
await context.Response.WriteAsync("Middleware Use Last Start");
await next.Invoke();
await context.Response.WriteAsync("Middleware Use Last End");
});
}
}
运行结果
可以看到按照顺序执行了 Middleware 1
Middleware 2
,最后一个注册的中间件没有被执行,因为mvc中,如果请求与路由匹配,则为终端
,短路了最后一个中间件的处理。
使用Run
可以注册终端中间件,加入到 Middleware 2
下面
app.Run(async (context) =>
{
await context.Response.WriteAsync("Middleware 3 \n");
});
运行结果
自定义
- 自定义类
public class MyMiddleware1
{
private readonly RequestDelegate _next;
public MyMiddleware1(RequestDelegate next)
{
_next = next;
}
public async Task InvokeAsync(HttpContext context)
{
await context.Response.WriteAsync("MyMiddleware1 Start \n");
await _next.Invoke(context);
await context.Response.WriteAsync("MyMiddleware1 End \n");
}
}
Startup
中 app.UseMiddleware<MyMiddleware1>();
注册中间件
运行结果
- 实现IMiddleware
public class MyMiddleware2 : IMiddleware
{
public async Task InvokeAsync(HttpContext context, RequestDelegate next)
{
await context.Response.WriteAsync("MyMiddleware2 Start \n");
await next.Invoke(context);
await context.Response.WriteAsync("MyMiddleware2 End \n");
}
}
Startup
中 app.UseMiddleware<MyMiddleware2>();
注册中间件
ConfigureServices
中向IOC容器注册services.AddSingleton<MyMiddleware2>();
运行结果
查看源码看看这俩种方式的区别
class UseMiddlewareExtensions
关键代码
internal const string InvokeMethodName = "Invoke";
internal const string InvokeAsyncMethodName = "InvokeAsync";
public static IApplicationBuilder UseMiddleware(this IApplicationBuilder app, Type middleware, params object[] args);
如果实现IMiddleware
if (typeof(IMiddleware).GetTypeInfo().IsAssignableFrom(middleware.GetTypeInfo()))
{
// IMiddleware doesn't support passing args directly since it's
// activated from the container
if (args.Length > 0)
{
throw new NotSupportedException(Resources.FormatException_UseMiddlewareExplicitArgumentsNotSupported(typeof(IMiddleware)));
}
return UseMiddlewareInterface(app, middleware);
}
从IOC容器获取IMiddlewareFactory
private static IApplicationBuilder UseMiddlewareInterface(IApplicationBuilder app, Type middlewareType)
{
return app.Use(next =>
{
return async context =>
{
var middlewareFactory = (IMiddlewareFactory)context.RequestServices.GetService(typeof(IMiddlewareFactory));
if (middlewareFactory == null)
{
// No middleware factory
throw new InvalidOperationException(Resources.FormatException_UseMiddlewareNoMiddlewareFactory(typeof(IMiddlewareFactory)));
}
var middleware = middlewareFactory.Create(middlewareType);
///......
public interface IMiddlewareFactory
{
IMiddleware Create(Type middlewareType);
void Release(IMiddleware middleware);
}
MiddlewareFactory 中的实现
public class MiddlewareFactory : IMiddlewareFactory
{
private readonly IServiceProvider _serviceProvider;
public MiddlewareFactory(IServiceProvider serviceProvider)
{
this._serviceProvider = serviceProvider;
}
public IMiddleware Create(Type middlewareType)
{
return ServiceProviderServiceExtensions.GetRequiredService(this._serviceProvider, middlewareType) as IMiddleware;
}
}
有此可知,实现IMiddleware注册中间件,还需要将类注入到容器
另一种无约束注册
var methods = middleware.GetMethods(BindingFlags.Instance | BindingFlags.Public);
var invokeMethods = methods.Where(m =>
string.Equals(m.Name, InvokeMethodName, StringComparison.Ordinal)
|| string.Equals(m.Name, InvokeAsyncMethodName, StringComparison.Ordinal)
).ToArray();
查找方法Invoke
InvokeAsync
是否存在,存在即可。
==注意,当Response已经发生,不要改变响应中的关键信息,如 HTTP Status Code
context-type
,...,会发生错误==
END
参考
ASP.NET Core Middleware microsoft
原文地址:https://www.cnblogs.com/DaWeiCnblogs/p/12169174.html