WebAPI-中间件
ASP.NETCore中,filter的概念更像是一个面向AOP编程的增强类
而ASP.NETCore中间件的概念,更像是JavaWeb的Filter或者是SpringMVC中的拦截器一样
需要注意的是,Java中也有中间件的概念,不过更多指的是Tomcat或Redis这一类的应用服务
大部分时间,我们极少需要自己定义中间件,一般都使用框架定义好的中间件,所以对框架提供的中间件要熟悉,另外要熟悉HttpContext对象的常用成员
Map管道
在启动类中,我们可以见到很多app.Use方法来定义的中间件
在这里,我们可以使用Map来自定义管道,实现不同的http请求路径而使用不同的中间件
定义在Map管道之外的中间件,则应用于所有请求
除了Map方法之外,还有MapGet、MapPost、MapWhen等指定管道的方法,但实际项目中,如果不是开发框架,比较少用到Map
中间件的注册顺序很重要
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32
| public class Program { public static void Main(string[] args) { var builder = WebApplication.CreateBuilder(args); var app = builder.Build();
app.Map("/test", async testBuilder => { testBuilder.Use(async (context, next) => { context.Response.ContentType = "text/html"; await context.Response.WriteAsync("1 Start<br/>"); await next.Invoke(); await context.Response.WriteAsync("1 End<br/>"); }); testBuilder.Use(async (context, next) => { await context.Response.WriteAsync("2 Start<br/>"); await next.Invoke(); await context.Response.WriteAsync("2 End<br/>"); }); testBuilder.Run(async ctx => { await ctx.Response.WriteAsync("hello,it is run<br/>"); }); });
app.Run(); } }
|
Context
每一次HTTP请求,框架会自动生成一个HttpContext类型的对象,称之为上下文,可以记录了请求路径、请求参数、请求客户端、响应报文、响应流、用户、自定义Items等信息。在中间件的前后逻辑和控制器中,均可以对HttpContext对象进行读写操作
Next
在一个中间件中,有三部分组织,①前逻辑;②next方法;③后逻辑
HTTP请求到达服务器后,先由框架进行请求解析,然后进入第一个中间件,先执行前逻辑,然后由中间件自己决定是否执行next.Invoke(),如不执行,则请求中断,如执行,则请求进入下一个中间件
当Controller控制器方法执行之后,再逆向执行中间件进行响应处理
中间件类
同样的,我们可以自定义中间件类,将中间件代码放入其中
中间件类是一个很普通的类,他不需要继承任何父类方法或实现任何接口,但这个类需要有一个构造方法,构造方法至少有一个RequestDelegate类型的参数
这个类型的参数对象(next)用来放行中间件,让其到达下一个中间件
这个类需要定义一个名字为Invoke或InvokeAsync的方法,方法至少有一个HttpContext类型的参数(context),其方法的返回值必须是Task类型
注:无论是中间件类还是Invoke方法,都可以通过DI来注入其他对象
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
| using Microsoft.AspNetCore.Http; using System; using System.Threading.Tasks;
public class LoggingMiddleware { private readonly RequestDelegate _next;
public LoggingMiddleware(RequestDelegate next) { _next = next; }
public async Task InvokeAsync(HttpContext context) { Console.WriteLine($"Request started: {context.Request.Method} {context.Request.Path}");
await _next(context);
Console.WriteLine($"Request completed with status code: {context.Response.StatusCode}"); } }
|
注册中间件
需要注意的是,通过UseMiddleware<>方法注册自定义中间件,而不是Use方法
1 2 3 4 5 6 7 8 9 10 11 12 13
| public class Program { public static void Main(string[] args) { var builder = WebApplication.CreateBuilder(args); var app = builder.Build(); app.UseMiddleware<TestMiddleware>();
app.Run(); } }
|
深度理解
ASP.NETCore框架内置很多中间件,通过这些内置的中间件,我们可以快速的构建一个WebAPI甚至是MVC的架构
对于Filter(筛选器)而言,他们有一些相同点和不同点:
- 中间件可以处理所有的请求,而Filter只能处理对控制器的请求
- 中间件运行在一个更底层、更抽象的级别
- 中间件和Filter可以完成很多相似的功能,例如:
- 未处理异常中间件和未处理异常Filter
- 请求限流中间件和请求限流Filter
- 优先选择使用中间件