附上demo实例 可以看到中间件的执行顺序如下 层层嵌套
next.Invoke(context)和 next(context)写法没区别
第一个next.Invoke(context)表示执行它下面的第二个context方法
第二个next.Invoke(context)表示执行它下面的第三个context方法直到调用到最后一个context方法 它才会返回自己下面没执行的方法 执行完自己的方法 以此类推到调用的那个母方法 直到最开始调用context的方法
可以看到输出结果是这样的
视图展示
自定义中间件搭建
继续在上面的demo中添加一个自定义的中间件 附代码
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)//应用程序的建造者
{
Func<RequestDelegate, RequestDelegate> middleware1 = next =>
{
return async context =>
{
await context.Response.WriteAsync("<p>this is middleware 1 start");
await next(context);
await context.Response.WriteAsync("<p>this is middleware 1 end");
};
};
app.Use(middleware1);
Func<RequestDelegate, RequestDelegate> middleware2 = next =>
{
return async context =>
{
await context.Response.WriteAsync("<p>this is middleware 2 start");
await next(context);
await context.Response.WriteAsync("<p>this is middleware 2 end");
};
};
app.Use(middleware2);
Func<RequestDelegate, RequestDelegate> middleware3 = next =>
{
return async context =>
{
await context.Response.WriteAsync("<p>this is middleware 3 start");
await next(context);//注意这里上面的图是没有的 这里有 是为了测试自定义中间件的加入
await context.Response.WriteAsync("<p>this is middleware 3 end");
};
};
app.Use(middleware3);
//自定义中间件
app.UseMiddleware<RequestIPMiddleware>();
}
定义一个RequestIPMiddleware类
public class RequestIPMiddleware
{
// 私有字段
private readonly RequestDelegate _next;
/// <summary>
/// 公共构造函数,参数是RequestDelegate类型
/// 通过构造函数进行注入,依赖注入服务会自动完成注入
/// </summary>
/// <param name="next"></param>
public RequestIPMiddleware(RequestDelegate next)
{
_next = next;
}
/// <summary>
/// Invoke方法
/// 返回值是Task,参数类型是HttpContext 这个方法必须有
/// </summary>
/// <param name="context">Http上下文</param>
/// <returns></returns>
public async Task Invoke(HttpContext context)
{
await context.Response.WriteAsync($"<p>User IP:{context.Connection.RemoteIpAddress.ToString()}\r\n");
// 调用管道中的下一个委托 这里注释掉是为了回调之前的中间件中的方法 最后的一个中间件是不允许有next.Invoke的 否则不回回调之前的中间件就结束了 因为它找不到下一个context
//await _next.Invoke(context);
}
}
实现效果
小扩展 同时也可以使用扩展中间件的方法调用中间件
再建一个类 用于扩展RequestIPMiddleware方法
public static class RequestIPExtensions
{
/// <summary>
/// 扩展方法,对IApplicationBuilder进行扩展
/// </summary>
/// <param name="builder"></param>
/// <returns></returns>
public static IApplicationBuilder UseRequestIP(this IApplicationBuilder builder)
{
return builder.UseMiddleware<RequestIPMiddleware>();
}
}
在startup中修改代码
app.UseRequestIP();//替换成这个
//app.UseMiddleware<RequestIPMiddleware>();
自定义中间件总结:
自定义中间件类
第一,它包含一个带有RequestDelegate类型参数的构造函数,这个RequestDelegate类型的参数表示在请求管道中的下一个中间件;
第二,它包含一个Invoke方法,该方法接受一个HttpContext类型的参数,并且这个方法的返回值为Task,这个HttpContext类型的参数即表示传入的HTTP请求。以下是一个典型自定义中间件:
第三,注册启用中间件IApplicationBuilder.UseMiddleware()