上篇介绍了Program.cs中Main作了什么,这篇咱们来讨论下Startup.cs它又作了什么呢?html
咱们新建一个Asp.Net Core Mvc项目,先来开一下Startup的代码ios
public class Startup { public Startup(IConfiguration configuration) { Configuration = configuration; } public IConfiguration Configuration { get; } // This method gets called by the runtime. Use this method to add services to the container. public void ConfigureServices(IServiceCollection services) { services.Configure<CookiePolicyOptions>(options => { // This lambda determines whether user consent for non-essential cookies is needed for a given request. options.CheckConsentNeeded = context => true; options.MinimumSameSitePolicy = SameSiteMode.None; }); services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2); } // This method gets called by the runtime. Use this method to configure the HTTP request pipeline. public void Configure(IApplicationBuilder app, IHostingEnvironment env) { if (env.IsDevelopment()) { app.UseDeveloperExceptionPage(); } else { app.UseExceptionHandler("/Home/Error"); // The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts. app.UseHsts(); } app.UseHttpsRedirection(); app.UseStaticFiles(); app.UseCookiePolicy(); app.UseMvc(routes => { routes.MapRoute( name: "default", template: "{controller=Home}/{action=Index}/{id?}"); }); } }
Startup包含两个方法,咱们先来分析一下ConfigureServices。经过方法上面的注释能够看到,这个方法是被.Net运行时调用的,实际上Asp.Net Core提供了内置的IOC容器,此方法就是用来将咱们本身的服务Service注入到Ioc容器当中。那么如何注入呢?固然是利用该方法的参数IServiceCollection进行注入。若是是咱们自定义的Service,可使用services.AddTransient<IStudentRepository,MockStudentRepository>()或其余的两种方式Singleton/Scoped来注入,具体区别看下面代码。若是是注入.Net Core自带的,通常是使用AddMvc,AddCors()。web
public void ConfigureServices(IServiceCollection services) { //单例注入,建立的对象在全部的地方全部的请求会话建立的都是相同 services.AddSingleton<IStudentRepository, MockStudentRepository>(); //瞬时注入,每次都建立一个新的对象 services.AddTransient<IStudentRepository, MockStudentRepository>(); //做用域注入,建立的对象在同一个请求会话时是相同的 services.AddScoped<IStudentRepository, MockStudentRepository>(); //注入MVC模块,包含MvcCore和经常使用第三方库的服务和方法 services.AddMvc(); //只包含核心的Mvc功能 services.AddMvcCore(); }
接下来咱们来看一下另外一个方法Configure。它是用来配置Asp.Net Core Mvc的Http请求管道的。Asp.Net Core的http请求管道与咱们以前的Asp.Net Mvc的请求管道有着很大的差异,它引入了中间件的概念,更像是一种责任链的模式。json
如今咱们就先来分析一下,参数IHostingEnvironment env,顾名思义是web宿主的环境变量相关的。在咱们的实际开发中,咱们经常会将咱们的环境分红:开发环境development,继承环境integration,测试环境testing,预发布环境staging,生产环境production。那这个环境是怎么配置的呢?实际上它是经过 ASPNETCORE_ENVIRONMENT 这个环境变量来配置运行时的环境的。cookie
通常咱们的配置遵循:app
一、开发机器上,能够在launchingsetting.json文件中设置该环境变量async
二、在预发布环境staging或生产环境production下,尽可能将该变量设置在操做系统中的环境变量里,由于上篇咱们也讲到,Asp.Net Core启动读取变量配置的时候是会依次覆盖的。测试
三、除了Asp.Net Core提供的development,staging,production外,咱们能够定义其余的环境,经过调用 env.IsEnvironment("自定义的环境变量");来判断是否处于此环境。ui
通常咱们能够配置开发环境下显示错误的方式以下面代码。this
if (env.IsDevelopment()) { DeveloperExceptionPageOptions developerExceptionPageOptions = new DeveloperExceptionPageOptions(); developerExceptionPageOptions.SourceCodeLineCount = 50; //异常显示行数 app.UseDeveloperExceptionPage(); //开发者异常页面 }
在咱们继续往下看代码以前,先来了解一下Asp.Net Core的中间件这个概念。
中间件是组装到应用程序管道中以处理请求和响应的软件,Asp.Net Core自带了不少的中间件,能够看下下图展现的中间件,能够看到请求通过Logging -> StaticFiles -> MVC后处理完再从MVC -> StaticFiles -> Logging返回给调用方。
其中MVC为终端中间件,终端中间件表示执行完这个中间件的时候就已经结束了,不会再往下调用其余的管道中间件了,这也是咱们建立完项目后看到最后一个是app.UseMvc的缘由。
关于中间件咱们须要注意的:
一、中间件能够同时被访问和请求
二、能够处理请求后,将请求传递给下一个中间件
三、能够处理请求后,使管道短路
四、能够处理传出响应
五、中间件是按照添加的顺序执行的
如今咱们来具体分析下Configure里面是怎么配置管道的。IApplicationBuilder app 参数为咱们提供了不少扩展方法,经过这些方法能够配置咱们的中间件。首先咱们来看Asp.Net Core提供的Use,Map,Run方法。
Use
方法可使管道短路(即,能够不调用下一个中间件)。咱们再Configure方法中调用app.Use方法,若是咱们在该方法中不调用next()方法,那么请求到达该方法就结束返回了,不会再往下一个中间件执行,即后面的Run不会执行。
app.Use(async (context, next) => { context.Response.ContentType = "text/plain;charset=utf-8;"; //解决中文乱码 await context.Response.WriteAsync("这是第一个Hello World"); //await next(); //调用下一个中间件 }); app.Run(async (context) => { //获取当前进程名 await context.Response.WriteAsync( System.Diagnostics.Process.GetCurrentProcess().ProcessName); });
若是咱们放开了next(),则会继续往下执行
再看一下下面的代码
app.Use(async (context, next) => { context.Response.ContentType = "text/plain;charset=utf-8;"; //解决中文乱码 await context.Response.WriteAsync("Use1以前"); await next(); //调用下一个中间件 await context.Response.WriteAsync("Use1以后"); }); app.Use(async (context, next) => { await context.Response.WriteAsync("Use2以前"); await next(); //调用下一个中间件 await context.Response.WriteAsync("Use2以后"); });
app.Run(async (context) => { //获取当前进程名 await context.Response.WriteAsync( System.Diagnostics.Process.GetCurrentProcess().ProcessName); });
咱们能够看到,请求过来后,以链式的方式执行: Use1以前 --> next --> Use2以前 --> next --> Run --> Use2以后 --> Use1以前。
Run
方法是一个约定, 而且一些中间件组件可能暴露在管道末端运行的Run [Middleware]方法,若是将Run放在了Configure里面,它也是终端中间件。
app.Run(async (context) => { context.Response.ContentType = "text/plain;charset=utf-8;"; //解决中文乱码 //获取当前进程名 await context.Response.WriteAsync("当前进程名:" + System.Diagnostics.Process.GetCurrentProcess().ProcessName); });
Map*
扩展用做分支管道的约定。映射根据给定的请求路径的匹配来分支请求流水线,若是请求路径以给定路径开始,则执行分支。
private static void HandleMapTest1(IApplicationBuilder app) { app.Run(async context => { await context.Response.WriteAsync("Map Test 1"); }); } private static void HandleMapTest2(IApplicationBuilder app) { app.Run(async context => { await context.Response.WriteAsync("Map Test 2"); }); } app.Map("/map1", HandleMapTest1); app.Map("/map2", HandleMapTest2);
最后咱们再来看一下Asp.Net Core提供的一些其余的中间件。
/*自定义默认页(第一种方式)*/ //DefaultFilesOptions defaultFilesOptions = new DefaultFilesOptions(); //defaultFilesOptions.DefaultFileNames.Clear(); //defaultFilesOptions.DefaultFileNames.Add("custom.html"); //自定义默认页 //app.UseDefaultFiles(defaultFilesOptions); /**************************************************************************/ /*自定义默认页(第二种方式)*/ //FileServerOptions fileServerOptions = new FileServerOptions(); //fileServerOptions.DefaultFilesOptions.DefaultFileNames.Clear(); //fileServerOptions.DefaultFilesOptions.DefaultFileNames.Add("custom.html"); //app.UseFileServer(fileServerOptions); //集合了UseStaticFiles,UseDefaultFiles,UseDirectoryBrowser /************************************************/ //app.UseDefaultFiles(); //添加默认文件中间件,必须注册在UseStaticFiles前 index.html index.htm default.html default.htm app.UseStaticFiles(); //添加静态文件中间件 //app.UseDirectoryBrowser();//暴露项目文件夹,不推荐使用 app.UseMvcWithDefaultRoute();//在请求管道中添加带默认路由的MVC
好了,这篇博文介绍了Startup文件作了哪些事情,其中最重要的就是中间件,那么下一篇就来聊聊Asp.Net Corez中的中间件吧。