作为一个合格的搬砖程序员,小妹打开了VS2019搭建了人生中的第一个.NetCore项目,根据IDE工具的提示搭建好项目后,在初始项目中我们会发现有这么几个文件
内部文件简介:
Properties&launchSettings.json 是一个启动配置文件,其用于应用的启动准备工作,包括环境变量,开发端口等。
Program类是项目的启动项,会为我们创建并初始化Web应用,并通过Startup类中的ConfigureServices和Configure方法,完成依赖注入和中间件管道的搭建。
Startup类
看到这,小妹有点懵了,啥是中间件?怎么配置中间件?额…带着问题找答案。百度了一下:
啥是中间件(Middleware)?
1.中间件是组装到应用程序管道中以处理请求和响应的软件。
2.每个组件选择是否将请求传递给管道中的下一个组件。
3.每个组件可以在调用管道中的下一个组件之前和之后执行工作。
4.请求委托(Request delegates)用于构建请求管道,处理每个HTTP请求。
怎么配置中间件?
请求委托使用Run,Map和Use扩展方法进行配置。单独的请求委托可以以内联匿名方法(称为内联中间件)指定,或者可以在可重用的类中定义它。这些可重用的类和内联匿名方法是中间件或中间件组件。请求流程中的每个中间件组件都负责调用流水线中的下一个组件,如果适当,则负责链接短路。
将HTTP模块迁移到中间件解释了ASP.NET Core和以前版本(ASP.NET)中的请求管道之间的区别,并提供了更多的中间件示例。
使用 IApplicationBuilder 创建中间件管道
ASP.NET Core请求流程由一系列请求委托组成,如下图所示(执行流程遵循黑色箭头):
每个委托可以在下一个委托之前和之后执行操作。委托还可以决定不将请求传递给下一个委托,这称为请求管道的短路。短路通常是可取的,因为它避免了不必要的工作。例如,静态文件中间件可以返回一个静态文件的请求,并使管道的其余部分短路。需要在管道早期调用异常处理委托,因此它们可以捕获后面管道的异常。
最简单的可能是ASP.NET Core应用程序建立一个请求的委托,处理所有的请求。此案例不包含实际的请求管道。相反,针对每个HTTP请求都调用一个匿名方法。
直接上代码吧!
上面文章说道中间件是应用程序管道中以处理请求和响应的软件,主要用委托实现,请求委托使用Run,Map和Use扩展方法进行配置
一、app.Run
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
app.Run(async context =>
{
await context.Response.WriteAsync("I'm Run1\r\n");
});
app.Run(async context =>
{
await context.Response.WriteAsync("I'm Run2\r\n");
});
}
运行IIS发现只运行了第一个中间件
说明确实在第一个app.Run终止了管道
结论:Run方法是一个约定, 并且一些中间件组件可能暴露在管道末端运行的或者不执行下一个中间件时可以使用Run [Middleware]方法
二、app.Use
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
app.Use(async (context, next) =>
{
await context.Response.WriteAsync("I'm Use1\r\n");
});
app.Run(async context =>
{
await context.Response.WriteAsync("I'm Run2\r\n");
});
}
运行结果,怎么肥事??不是说Use是内联中间件吗?为啥没有运行下一个中间件的方法??
仔细看以上的代码段,Use方法比Run方法多了一个参数next,next参数表示管道中的下一个委托,没有调用next.Invoke();尾端的Middleware即Run方法内没有执行。我们再修改代码。
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
app.Use(async (context, next) =>
{
await context.Response.WriteAsync("I'm Use1\r\n");
await next.Invoke();
});
app.Run(async context =>
{
await context.Response.WriteAsync("I'm Run2\r\n");
});
}
运行结果:执行了两个委托
总结:使用Use方法,而没有调用next.Invoke(),Use的效果与Run的效果是一致的。调用next.Invoke()后Use与Run代码段都被执行了。需要注意的是,管道中可以增加多个middleware(中间件),他们是按顺序执行的,执行的顺序与在Configure方法中代码的顺序是一致的。
三、Map和MapWhen
Map比较不同,它将Middleware(中间件)添加到管道中,它是在管道中增加了分支。通过影射路径的方式,增加管道分支。我们保留上面例子,并增加代码。如下:
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
app.Use(async (context, next) =>
{
await context.Response.WriteAsync("I'm Use1\r\n");
await next.Invoke();
});
app.Map("/maptest", MapTest);//映射路径访问指定的Middleware
app.Run(async context =>
{
await context.Response.WriteAsync("I'm Run2\r\n");
});
}
private static void MapTest(IApplicationBuilder app) {
app.Use(async (context,next)=> {
await context.Response.WriteAsync("this is maptest \r\n");
await next.Invoke();
});
}
启动iis,在地址后面增加映射的地址如:https://localhost:44301/maptest,运行结果:
maptest分支被执行了
MapWhen:顾名思义满足条件的情况下执行相应的方法
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
app.Use(async (context, next) =>
{
await context.Response.WriteAsync("I'm Use1\r\n");
await next.Invoke();
});
//app.Map("/maptest", MapTest);//映射路径访问指定的Middleware
//如果有URL中的参数包含了zz,满足这个条件,就执行MapTest
app.MapWhen(context=> { return context.Request.Query.ContainsKey("zz"); }, MapTest);
app.Run(async context =>
{
await context.Response.WriteAsync("I'm Run2\r\n");
});
}
private static void MapTest(IApplicationBuilder app) {
app.Use(async (context,next)=> {
await context.Response.WriteAsync("this is maptest \r\n");
await next.Invoke();
});
}
如果有URL中的参数包含了zz,满足这个条件,就执行MapTest,地址:https://localhost:44301/?zz=1,运行结果:
通过以上的操作,小妹好像已经了解了什么是管道,什么是中间件,ASP.NET Core提供了附带中间件组件,如下:
中间件 | 描述 |
---|---|
Authentication | 提供身份验证支持 |
CORS | 配置跨域资源共享 |
Response Caching | 提供缓存响应支持 |
Response Compression | 提供响应压缩支持 |
Session | 提供用户会话管理 |
Static Files | 为静态文件和目录浏览提供服务提供支持 |
URL Rewriting Middleware | 用于重写 Url,并将请求重定向的支持 |
好了,有啥总结的不好的,请各位大神多多指教。回家!