## 官方说明
中间件是一种装配到应用管道以处理请求和响应的软件。 每个组件:
- 选择是否将请求传递到管道中的下一个组件。
- 可在管道中的下一个组件前后执行工作。
请求委托用于生成请求管道。 请求委托处理每个 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