5:中间件
♣ 视频地址:https://www.bilibili.com/video/av38392956/?p=4
1:这节讲的还是中间件
1.1:当我们ASP.NET Core应用开始执行的时候,我们使用了Builder来配置WebHost,这里面我们注册了一个类Startup,让Startup来配置我们Web应用的启动逻辑,这里使用的方法是UseStartup,ASP.NET Core就会实例化这个类并调用这个类里面的那两个方法;
1.2:第一个就是ConfigureServices,在这个方法里可以注册服务,注册完这些服务后,这些服务就可以被注入到其他方法或类里进行使用,这些注册的服务包括我们自己写的服务IWelcomeService,也包含ASP.NET Core预定义好的服务,这些预定义好的有些服务默认是没有进行注册的,所以我们还需要在这里进行一下注册;
1.3:第二个就是Configure方法,这个方法里的内容只执行一次。在这个方法里,我们实现了IApplicationBuilder一个对象,使用它来配置我们的中间件,所以我们要精确的配置中间件,以便这些中间件组合起来能够正确的处理Http请求,并返回响应;
1.4:我们先把if判断去掉,这时就剩一个中间件了,是我们自己写的,但是在真实的项目里,我们很少使用app.Run这个方法,通常Run里面配的都是简单的中间件
1.5:真实项目里,我们通常使用app.Use开头的这些方法,UseCors是跨域的,Use开头的这些方法把中间件代码都封装到另外的方法或类里面了;
1.6:我们使用一个欢迎页app.UseWelcomePage()
1.6.1:然后运行,看效果
1.6.2:我们换个路由,在后面加/Home/hahaha,发现效果还是不变,我们可以发现他的路由工作方式,不管你进来是什么请求,参数,路径,都返回欢迎页,到app.UseWelcomePage就返回了,后面的中间件就不会走了
1.6.3:我们也可以在方法里传参数,通过参数的设定来配置中间件,比如我们加一个路径Path=“/welcome”
1.6.4:F5运行看效果,默认根路径下走的是app.Run(),当在路径下面加/welcome时,才会跳到欢迎页,如果不加或者加别的,是不会加载的
1.7:还有一个写法app.Use(),在参数里来配置这个中间件,我们可以看到app.Use的参数是一个Func<>,Func<>本身的参数类型是RequestDelegate,返回类型也是RequestDelegate,而RequestDelegate类型就是一段可执行的代码
1.7.1:我们先看app.Run,它的参数就是RequestDelegate,它把接收的HttpContext作为参数,返回类型是一个Task,所以它通常是一个异步的方法async Method
1.7.2:所以app.Use需要一个function,这个function有个参数,我们叫它next,现在这个next类型就是RequestDelegate类型,这个RequestDelegate代表的意思是在管道里,下一个要执行的中间件;如果我在里面选择调用这个next,那意思就是我允许下一个中间件来处理Http请求;
1.7.3:而这个中间件返回的类型还是一个RequestDelegate,它需要传入一个httpContext作为它的参数,在箭头里需要返回一个Task对象
1.7.4:同时做一个逻辑,根据它请求路径不同,让它走不通的中间件,F5看效果
1.7.5:默认走Hello From IWelcomeService,加上/first,走First!!!,加/welcome走欢迎页,输入其他地址,走的是Hello From IWelcomeService;
1.7.6:为了看走的明细,我们把日志加进来,Logger已经注册到服务里了,是预先注册的,所以我们可以直接把它注入进来;
1.7.7:还有日志也写完了,看效果,我们可以看到app.Use()日志首先被执行了
1.7.8:然后我们做一下请求,在浏览器输入localhost:5000/first,然后再打开命令提示符,1是我们的请求;2和3分别是执行了日志,其中3是--First
1.7.9:我们再输入个其他请求http://localhost:5000/welcome,可以看到3走的是----next(httpContext)
1.7.10:我们发现,app.Use()只走了一遍,如下图红框里,绿框外的这一段看做一个方法,这个方法在启动配置的时候走了一遍,走一次
1.7.11:绿框里才是中间件代码,每次请求,如果之前没有中间件拦截的话都会走到这
2:如果我们在中间件里抛出异常,那么会发生什么。。。
2.1:运行,能看到,它返回的是 HTTP ERROR 500
2.2:我们作为开发者,可能会需要错误的详细信息,所以我们就需要使用下面这个中间件
2.3:我们把注释去掉,然后再运行,可以看到和刚才显示的不一样了,在这里提示“有一个未处理的异常发生了在处理请求的时候”,并且告诉我们是在第32行抛出的异常
2.4:我们这个app.UseDeveloperExceptionPage()中间件是放在比较靠前的位置,因为比较靠前,所以在它之后的中间件里如果抛出了异常,这时候我们的开发者异常页面(UseDeveloperExceptionPage)就会显示出来,简而言之就是这个可以捕获异常;
2.5:如果不使用这个中间件,就会返回500状态码,响应并没有返回,之前没使用中间件时返回500状态码的页面是Chrome浏览器内置的一个页面,如果你使用其他的浏览器,可能页面是不一样的;
2.6:这个开发者异常页面只适合给开发者来看,如果是最终客户就不应该看到这个页面,因为异常页面有很多详细信息,如果是黑客的话,哼哼,自己招楞着办,,,所以我们要全部取消注释
2.7:下面的意思是在开发的环境里,可以使用app.UseDeveloperExceptionPage(),否则就不使用这个中间件
3:环境
3.1:这个环境IsDevelopment,是指我们运行时的环境,而我们的应用呢,可以使用IHostingEnvironment这个服务来获取我们的这个应用到底是运行于哪个环境里;
3.2:这里面说的环境通常是指开发环境,生产环境或者是测试环境
3.3:看一下env里面都有什么,ApplicationName=应用程序的名,ContentRootPath=“内容根路径”,EnvironmentName="环境变量名",WebRootPath=“Web根路径”,还可以根据IsDevelopment(开发环境),IsProduction(生产环境),IsStaging(预览环境)来判断当前环境
3.4:上面是设置环境变量值(通常不是这么设置的),下面是判断当前环境变量值是不是IntegrationTest,
3.5:那环境变量有值,那它的名呢,如下图:ASPNETCORE_ENVIRONMENT这个是环境变量的属性名
3.6:那为什么我们用VS进行调试的时候,它会启动这个中间件呢?是因为在调试的时候,它这个环境变量的值是Development。
3.7:但是它是在哪里设置的呢?就是上图中launchSettings.json中,刚才使用IIS Express运行,它走了“IIS Express”里的配置,这段配置里environmentVariables就是设置环境变量,在这里把属性名为ASPNETCORE_ENVIRONMENT的值设为Development,所以我们一运行就是Development环境,所以会加载下图的中间件
3.8:我们也可以右键项目,选择属性,在调试里修改环境,我在这里改为Production,保存
3.9:可以看到,launchSettings.json的值也变为了Production
3.10:我们的一个Web项目,可以设置多个启动档案,这里面就有两个,第一个是IIS Express;第二个就是dotnet run运行的,就是命令行运行的,启动目录是localhost:5000
3.11:那么VS2017运行时执行的那个档案呢,我看到执行按钮旁有个下拉,看到有IIS Express和Tutorial.Web,这两个名字对应的就是上图中的名字
3.12:回到Startup类,所以环境为非开发时,使用另一个中间件app.UseExceptionHandler();
3.13:我们也可以在appsettings.json,它也可以根据环境来选择是否附加其他的文件,下面这个appsettings.Development.json说明我们在开发环境的时候还会把这个文件给附加上去
3.14:之前也看过源码,首先加载appsettings.json,然后是appsettings. hostingEnvironment.EnvironmentName .json,就是把环境变量名放在这了,如果是开发环境就是appsettings.Development.json,开发环境会把上面的那个文件也给附加上去;如果是生产,那么它就会找appsettings.Production.json,但是上图中没有这个文件,所以生产环境目前只能使用这一个配置文件
4:真正的Web应用还需要伺服(server)一些文件,比如说js文件,css文件,或者html静态文件,如果你想伺服这些文件的话,你必须在ASP.NET Core项目里使用一个中间件叫伺服静态文件的中间件
4.1:ASP.NET Core默认配置只会从wwwroot这个文件夹里来伺服文件夹里的文件,我们首先创建这个文件夹,并且在里面创建一个index的html文件,并在里面写一句话
4.2:运行看到加载不出来
4.3:因为我们这个中间件目前只能读取到welcome的信息,如果想伺服wwwroot里面的文件,我们就需要使用app.UseStaticFiles这个中间件
4.4:这个时候再F5看一下,出来了
4.5:如果你想使用其他文件名作为默认文件,你可以在app.UseDefaultFiles()里面进行配置;注意:UseDefaultFiles()这个中间件它并不是伺服文件,它不会把index.html文件返回回去,它会改变请求路径,它把请求路径改成我们要找的文件,比如在这里我们要找index.html,它就把路径改成index.html,然后再把请求传送到下一个中间件,在这里就是UseStaticFiles(),然后UseStaticFiles()一看请求路径是index.html,他就会找到这个文件,并把这个文件返回去
4.6:还有另外一个中间件 app.UseFileServer(),这种中间件包含了上面两个中间件的功能,同时它还有些其他功能,包括目录浏览,所以我们直接使用这一个中间件就可以
4.7:我们用这个中间件试一下,看到请求根目录就会返回index.html