笔记内容来源于微软 MVP 杨旭老师 solenovex 的视频
Startup 类:注册服务和使用中间件
Startup类默认生成了两个方法,在这个类中主要负责注册服务和使用中间件。
让我们先来看一下Startup类的源码
Startup类的源码
在下面的源码中有ConfigureServices和Configure两个方法。
public void ConfigureServices(IServiceCollection services){} public void Configure(IApplicationBuilder app, IHostingEnvironment env) { if (env.IsDevelopment()) { app.UseDeveloperExceptionPage(); } app.Run(async (context) => { await context.Response.WriteAsync("Hello World!"); }); }
1.ConfigureServices方法
ConfigureServices方法是用来注册服务的,Configure方法是用来使用中间件的。
注册服务就是依赖注入,向Ioc容器中注入类型的对象,注入后就可以直接使用该类型注入实例,而无需再次实例化,减少了代码的耦合。
具体内容可以自行百度依赖注入/控制反转。
2.Configure方法
Configure方法配置了Http请求处理的管道,每个Http请求到达之后,会按照Configure方法中的组件来决定如何处理这些请求。
其中的app.Run方法以及匿名函数,就是不管什么请求到达这里,都会返回 context.Response.WriteAsync("Hello World!") 响应。
注册服务演示
我们先创建一个IWelcomeService接口以及实现该接口的WelcomeService类
public interface IWelcomeService { string GetMessage(); } public class WelcomeService : IWelcomeService { public string GetMessage() { return "Hello from IWelcomeService"; } }
然后在Startup类Configure方法中使用该接口类型对象,调用接口的GetMessage方法输出
事实上,运行后我们会发现直接使用是不行的,因为该类型刚还有在ConfigureServices方法中注册。
下面我们就在ConfigureServices方法中注册接口和实现类。
public void ConfigureServices(IServiceCollection services) { services.AddSingleton<IWelcomeService, WelcomeService>(); }
运行后的结果
Hello from IWelcomeService
注册服务的几种形式
注册服务时,我们使用的是AddSingleton方法,这是以单例的形式依赖注入对象,单例就是指该类型只有一个实例,具体含义和用法可以自行百度。
还有其他几种形式,如AddTransient方法,每次请求都会生成一个实例,AddScoped方法,每次Http请求都会生成一个实例。
管道和中间件
Configure方法配置了Http请求处理的管道。
假设有个Http请求到达了我们的Web应用,有一个POST请求,那么我们的Web应用就需要处理这个请求。中间件就是负责处理请求的,他将决定如何处理这些请求。
中间件其实就是个对象,每个中间件的角色和功能都不一样,并且局限在特定的领域内。每个中间件都很小,Web应用会用到很多中间件。
一个简单的中间件管道示例
假设一个POST请求Product,首先通过Logger中间件,Logger可以查看到很多的信息,记录下请求的信息,也可以拒绝请求。
然后转送到下个中间件,比如授权中间件。授权中间件会先找一个特定的cookie的值或者token,如果找到了就转发到下一个中间件。
下一个中间件可以是路由中间件。首先查看请求的URL,然后找到可以响应该请求的方法,就可以返回一个JSON/HTML,然后原路返回。
Startup类被调用的逻辑
搞清了Startup类中的方法的作用和能做什么后,我们来看一看Startup类是如何被调用的。
上一篇博文提到了Program类的CreateWebHostBuilder方法中调用了 UseStartup<Startup>() ,就是这个方法制定了Startup类为启动类,实例化Starup类得到实例,并调用类中的两个方法。
首先会调用ConfigureServices方法,注册服务。除了预先注册好的服务,自己写的类和一些没注册内置类都需要在该方法中注册。
然后调用Configure方法,该方法只会调用一次。在该方法中,我们使用实现了IApplicationBuilder接口的类型的对象,来配置中间件。
中间件的Use方法
默认的Run方法并不建议使用,项目中常常使用Use方法。除此之外还有内置的很多USeXxx方法。如UseWelcomePage方法就会调用欢迎页。这些方法的参数往往可以传递一个对象来对其进行配置。
还有直接使用Use方法更底层,其参数是一个Func<ReuquestDelegate,ReuquestDelegate>,Func的参数是ReuquestDelegate,
其返回类型也是ReuquestDelegate。ReuquestDelegate类型就是一段可执行的代码,例如下方代码,返回了一个异步Task,Task返回了httpContext对象。
app.Use(next => { return async httpContext => { if (httpContext.Request.Path.StartsWithSegments("/first")) { await httpContext.Response.WriteAsync("First!"); } else { await next(httpContext); } }; });
异常页面的中间件
下方代码首先判断当前环境是不是开发环境,如果是,当出现错误时就会使用开发者异常页面中间件。
因为开发者需要详细的错误信息,但是这些信息不能直接暴露,否则会被黑客轻易利用,因此只能在开发者环境下才需要调用开发者异常页面中间件。
if (env.IsDevelopment()) { app.UseDeveloperExceptionPage(); }
判断环境和自定义环境
前面讲到可以判断运行环境,事实上环境是可以自定义的,